标签:cin end 之间 int out turn 矛盾 code 思路
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3038
题目大意:
在一个长度为n的区间上,给出m个区间和,当遇到给出的这个区间与前面的区间有矛盾时,认为新给出的区间是错误的,不更新区间,问有多少错误区间。区间中的数是任意的。
解题思路:
首先我们定义一个数组$sum$,$sum[i]$存的是第i个数与他的祖宗这段区间的区间和,不包括祖宗点(祖宗点一定小于儿子点)。然后要搞清楚什么情况下可以判断出有冲突,先确定给出的$a(a=a-1),b$两点与他们的祖宗$aa,bb$两点,我们就确定了两个区间,我们要求的是$a$与$b$的距离,也就是两个区间交叉后的后边一段的距离,所以必须要确定出前边几段距离具体的值,所以,可以推出,只有祖宗点位置相同时才能得到$a$到$b$的具体值。接着要处理,当不冲突时更新$sum$数组,与$pre$数组。因为我们规定,祖宗点一定小于儿子点,所以,我们要找到$aa$与$bb$的关系,如$aa<bb$,则$pre[bb]=aa$,算出$sum[bb]$,那么,$a,b,aa,bb$之间的距离都可以表示出来。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define debug(a) cout<<#a<<":"<<a<<endl; 5 const int INF=0x3f3f3f3f; 6 const int N=1e6+7; 7 const int mod=1e9+7; 8 int maxn,minn; 9 int T,n,m; 10 int pre[N]; 11 int sum[N]; 12 13 int find(int a){ 14 if(pre[a]!=a){ 15 int b=pre[a]; 16 pre[a]=find(pre[a]); 17 sum[a]=sum[a]+sum[b]; 18 } 19 return pre[a]; 20 } 21 22 void join(int a,int b,int w){ 23 int aa=find(a); 24 int bb=find(b); 25 if(aa<bb){ 26 pre[bb]=aa; 27 sum[bb]=sum[a]-(sum[b]-w); 28 } 29 else{ 30 pre[aa]=bb; 31 sum[aa]=sum[b]-sum[a]-w; 32 } 33 } 34 35 int main(){ 36 int ans; 37 int a,b,w,aa,bb; 38 while(cin>>n>>m){ 39 memset(sum,0,sizeof(sum)); 40 for(int i=1;i<=n;i++){ 41 pre[i]=i; 42 } 43 ans=0; 44 for(int i=1;i<=m;i++){ 45 cin>>a>>b>>w; 46 a--; 47 aa=find(a); 48 bb=find(b); 49 if(aa==bb){ 50 if(sum[b]-sum[a]!=w){ 51 ans++; 52 } 53 } 54 else{ 55 join(a,b,w); 56 } 57 } 58 cout<<ans<<endl; 59 } 60 return 0; 61 }
HDU - 3038 How Many Answers Are Wrong (带权并查集)
标签:cin end 之间 int out turn 矛盾 code 思路
原文地址:https://www.cnblogs.com/meanttobe/p/12772861.html