码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3038 How Many Answers Are Wrong(带权并查集)

时间:2017-10-10 22:25:54      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:long   str   nbsp   continue   cto   ace   math   ios   题目   

题目链接: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(带权并查集)

标签:long   str   nbsp   continue   cto   ace   math   ios   题目   

原文地址:http://www.cnblogs.com/fu3638/p/7648107.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!