HDU 3038 How Many Answers Are Wrong(带权并查集)
Posted Yeader
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3038 How Many Answers Are Wrong(带权并查集)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1272
题目大意:有n条信息,每条信息都给出区间l到r的值,如果后面出现的信息与前面的矛盾,那么就算是一个错误信息,问一共给出多少错误信息。比如1给出三条信息1 4 10 ,1 2 5,3 4 6那么第三条就错了,因为[1,2]+[3,4]应为[1,4]等于10,而现在是11。
解题思路:对于l~r之间的和是sum,其实可以理解成r比l-1大sum,这样刚好可以跟前面一段区间连起来。再利用val[]记录r比l大的值,就变成常规的带权并查集了。
代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<vector> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<stack> 11 #include<string> 12 #define LC(a) (a<<1) 13 #define RC(a) (a<<1|1) 14 #define MID(a,b) ((a+b)>>1) 15 using namespace std; 16 typedef long long LL; 17 const int INF=0x3f3f3f3f; 18 const int N=2e5+5; 19 20 int root[N],val[N]; 21 22 int find(int x){ 23 if(root[x]==x) 24 return x; 25 int tmp=find(root[x]); 26 cout<<val[x]<<" "<<val[root[x]]<<endl; 27 val[x]+=val[root[x]]; 28 return root[x]=tmp; 29 } 30 31 int main(){ 32 int n,m,ans; 33 while(~scanf("%d%d",&n,&m)){ 34 ans=0; 35 memset(val,0,sizeof(val)); 36 for(int i=0;i<=n;i++){ 37 root[i]=i; 38 } 39 while(m--){ 40 int l,r,sum; 41 scanf("%d%d%d",&l,&r,&sum); 42 int t1=find(l-1); 43 int t2=find(r); 44 if(t1==t2){ 45 if(sum!=val[r]-val[l-1]) 46 ans++; 47 continue; 48 } 49 root[t2]=t1; 50 val[t2]=val[l-1]-val[r]+sum; 51 } 52 printf("%d\n",ans); 53 } 54 return 0; 55 }
以上是关于HDU 3038 How Many Answers Are Wrong(带权并查集)的主要内容,如果未能解决你的问题,请参考以下文章
hdu-3038 How Many Answers Are Wrong[并查集]
HDU3038 How Many Answers Are Wrong —— 带权并查集
HDU-3038-How Many Answers Are Wrong
HDU 3038 How Many Answers Are Wrong (带权并查集)