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<cstring> 3 #include<iostream> 4 using namespace std; 5 typedef long long LL; 6 const int INF=0x3f3f3f3f; 7 const int N=2e5+5; 8 9 int root[N],val[N]; 10 11 int find(int x){ 12 if(root[x]==x) 13 return x; 14 int tmp=find(root[x]); 15 val[x]+=val[root[x]]; 16 return root[x]=tmp; 17 } 18 19 int main(){ 20 int n,m,ans; 21 while(~scanf("%d%d",&n,&m)){ 22 ans=0; 23 memset(val,0,sizeof(val)); 24 for(int i=0;i<=n;i++){ 25 root[i]=i; 26 } 27 while(m--){ 28 int l,r,sum; 29 scanf("%d%d%d",&l,&r,&sum); 30 int t1=find(l-1); 31 int t2=find(r); 32 if(t1==t2){ 33 if(sum!=val[r]-val[l-1]) 34 ans++; 35 continue; 36 } 37 root[t2]=t1; 38 val[t2]=val[l-1]-val[r]+sum; 39 } 40 printf("%d\n",ans); 41 } 42 return 0; 43 }