题意:有一个数列,不知道数列里的数值,有多个询问,每个询问给出回答一段区间的和,但是有些是对的,有些是错的,保证如果无逻辑错误,则该回答认为是正确的,问哪些询问是错误的可以忽略。

对于询问区间和其实可以看做是前缀和,区间和也就是前缀和的差值,[a,b]的和就转换成 b 个元素的前缀和与 a-1 个元素的前缀和的差值,因此就转变为元素差值关系问题了,就可以用并查集与元素权值来判断,每个元素的权值代表其与根元素的值的差。注意读入 a、b 区间,需要对 a-1 和 b 进行合并。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 int fa[200005],num[200005],n,m;
 7 
 8 void init(){
 9     for(int i=1;i<=n;i++){
10         fa[i]=i;
11         num[i]=0;
12     }
13 }
14 
15 int find(int x){
16     int r=x,t1,t2,c=0;
17     while(r!=fa[r]){
18         c+=num[r];
19         r=fa[r];
20     }
21     while(x!=r){
22         t1=fa[x];
23         t2=c-num[x];
24         num[x]=c;
25         fa[x]=r;
26         c=t2;
27         x=t1;
28     }
29     return r;
30 }
31 
32 int main(){
33     while(scanf("%d%d",&n,&m)!=EOF){
34         init();
35         int i,ans=0;
36         for(i=1;i<=m;i++){
37             int a,b,v;
38             cin>>a>>b>>v;
39             a--;
40             int x=find(a),y=find(b);
41             if(x==y){
42                 if(num[b]-num[a]!=v)ans++;
43             }
44             else{
45                 fa[y]=x;
46                 num[y]=num[a]+v-num[b];
47             }
48         }
49         cout<<ans<<endl;
50     }
51     return 0;
52 }
View Code