1. 程式人生 > >HDU 3038 How Many Answers Are Wrong(帶權並查集)

HDU 3038 How Many Answers Are Wrong(帶權並查集)

define pro tor memset set sizeof fin printf class

題目鏈接: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(帶權並查集)