How Many Answers Are Wrong (HDU - 3038)(带权并查集)
并查集是用来对集合合并查询的一种数据结构,或者判断是不是一个集合,本题是给你一系列区间和,判断给出的区间中有几个是不合法的。
思考:
1.如何建立区间之间的联系
2.如何发现悖论
首先是如何建立联系,我们可以用一张图表示

假如说区间【fx,x】是之前建立的区间,他们之间和为sum[x],fx和x的联系可以用集合来存储,同理【fy,y】也是如此。当给出了一个新的区间【x,y】时,且区间和为s。
就产生了两种情况了,如果fx == fy 那么这两个区间是有关联的区间,也就是【x,y】之间的和是可以求出的。可以把这个图看成一个向量。
区间【x,y】的和就是可以写成sum[x] - sum[y]。
判断给出的s与向量法计算的区间和是否相等就可以判断是否是悖论。
当然如果fx != fy就需要建议新的区间关系。首先将fy指向fx,这代表fx是区间的左端点,计算sum【fy】= sum【x】- sum【y】+ s;这里同样用的是向量法。
这样建立联系与判断悖论都可以表达了,接下来就是一些细节了,比如在更新区间的时候要进行路径的压缩,压缩的过程中需要对权值进行更新,目的是使每个已知区间最大化。
解题思路:这个题乍一看可能要线段树或树状数组,其实没有必要,区间和可以理解为前缀和相减。
每个节点记录前缀和,对每个询问先判断两个节点是否连通,这便是带权并查集干的事了,若联通则权值相减看是否为给定值,若不为则矛盾;若不联通则两棵树合并为一棵(注意有顺序)同时计算出新的子节点的权值。
AC代码
#include<bits/stdc++.h>
using namespace std; const int maxn = + ; int pre[maxn] ,sum[maxn];//sum是该节点到其根的和,如sum【3】
//,3的根是1,就是1到3的和 int find(int x){
if(x == pre[x]) return x;
else { int root = find(pre[x]);
sum[x] += sum[pre[x]];
return pre[x] = root;
}
} void init(int n){
for(int i = ; i <= n;i++){
pre[i] = i;
sum[i] = ;
}
}
int ans = ;
void unions(int x,int y,int s){
int fx = find(x);
int fy = find(y);
if(fx != fy){
pre[fy] = fx;
sum[fy] = sum[x] - sum[y] + s;
}
else if(sum[y] - sum[x] != s)
ans ++; }
int main(){
int n,m;
//cin >> n >> m;
while(cin >> n >> m){
init(n);
int x,y;
int s;
ans = ;
while(m--){
cin >> x >> y >> s;
x --;
unions(x,y,s);
} cout << ans << endl;
} return ;
}
How Many Answers Are Wrong (HDU - 3038)(带权并查集)的更多相关文章
- HDU - 3038 带权并查集
这道题我拖了有8个月... 今天放假拉出来研究一下带权的正确性,还有半开半闭的处理还有ab指向的一系列细节问题 #include<iostream> #include<algorit ...
- hdu 3038带权并查集
#include<stdio.h> #include<string.h> #define N 200100 struct node { int x,count; }pre[N ...
- HDU 3038 How Many Answers Are Wrong 【YY && 带权并查集】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=3038 How Many Answers Are Wrong Time Limit: 2000/1000 ...
- hdu 1829 带权并查集的运用类似于食物链但是更简单些
#include<stdio.h> #define N 1100000 struct node { int x,y; }f[N],pre[N]; int find(int x) { if( ...
- Zjnu Stadium HDU - 3047 带权并查集板子题
#include<iostream> #include<cstring> #include<cstdio> using namespace std; +; int ...
- HDU 3038 - How Many Answers Are Wrong - [经典带权并查集]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- HDU - 3038 How Many Answers Are Wrong (带权并查集)
题意:n个数,m次询问,每次问区间a到b之间的和为s,问有几次冲突 思路:带权并查集的应用.[a, b]和为s,所以a-1与b就能够确定一次关系.通过计算与根的距离能够推断出询问的正确性 #inclu ...
- hdu 3038 How Many Answers Are Wrong【带权并查集】
带权并查集,设f[x]为x的父亲,s[x]为sum[x]-sum[fx],路径压缩的时候记得改s #include<iostream> #include<cstdio> usi ...
- HDU3038 How Many Answers Are Wrong —— 带权并查集
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 How Many Answers Are Wrong Time Limit: 200 ...
随机推荐
- 使用vue-resource请求数据的步骤
1.需要安装 vue-resource模块 注意加上--save npm install vue-resource --save 2.main.js 引入vue-resource import Vue ...
- xml转dict
xml转dict 最开始的时候一直是按格式比较严谨的XML格式进行的转换,所以一般只需要考虑两种情况就可以了,即各个节点或者子节点全相同或者全不同,全相同按list处理,全不同按dict处理,这么一想 ...
- 033:DTL常用过滤器(2)
date过滤器: date过滤器:将一个日期按照指定的格式,格式化成字符串.示例代码如下: views.py: from datetime import datetime def cur_date(r ...
- php strcspn()函数 语法
php strcspn()函数 语法 作用:输出在字符串中找到某字符之前查找的字符数.直线电机参数 语法:strcspn(string,char,start,length) 参数: 参数 描述 str ...
- vim 批量添加删除注释
vim中单行注释只是多行注释的一个特例,这里统一进行多行注释的讲解 (1)添加批量注释 ctrl+v 进入列编辑模式,向下或向上移动光标,把需要注释的行的开头标记起来,然后按大写的I(shift+i) ...
- [CSP-S模拟测试]:Median(暴力+模拟)
题目描述 定义两个数列: $$S=\{S(1),S(2),...,S(n)\}\text{和}S_2\{S_2(1),S_2(2),...,S_2(n)\}$$ $$S(k)=(p_k\times k ...
- xpath进阶
目标: 抓取页面列表信息,并且获取第四个单元格得指定属性 代码: import requests from lxml import etree resp = requests.get('http:// ...
- apache主要配置详解
1. # Deny access to the entirety of your server's filesystem. You must # explicitly permit access to ...
- 使用代理IP、高匿IP、连接失败
先百度一下,什么是代理IP 我们使用代理IP就是因为某些站点会屏蔽我们的IP,所以我们要动态的更换代理IP. 代理IP: 其中我们首先选择国内的IP,国外的一般都比较慢,其次不要选择如{新疆乌鲁木齐} ...
- EZOJ #389点分治好题
分析 一层一层把叶子去掉 看最多能去掉多少层即可 代码 #include<bits/stdc++.h> using namespace std; ],du[],fa[],n,m,ans; ...