有点意思的并查集
Posted lmcc1108
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有点意思的并查集相关的知识,希望对你有一定的参考价值。
K - How Many Answers Are Wrong HDU - 3038
题目大意:两个人玩游戏,一个人说一个区间内的数的和,然后判断她说的有多少句和之前说过的冲突的。
一开始想的用一个数就代表他到根节点里的数和,但是在路径压缩时明显不对,因为已知[1,8],[8,10]并不能推出[1,10],但如果是(1,8],(8,10]就可以推出(1,10]。所以关键在于一个左开右闭的区间。
1 #include<stdio.h> 2 struct Extent{ 3 int gen,sum;//sum为区间(gen,x]内的和 4 }E[201108]; 5 int gui(int x); 6 int bing(int x,int y,int z); 7 int main() 8 { 9 int n,m,i; 10 while(scanf("%d%d",&n,&m)!=EOF) 11 { 12 for(i=0;i<=n;i++) 13 { 14 E[i].gen=i; 15 E[i].sum=0;//一开始为空集即0 16 } 17 int x,y,z,ans=0; 18 while(m--) 19 { 20 scanf("%d%d%d",&x,&y,&z); 21 ans+=bing(x-1,y,z);//每次给的是[x,y]的值,所以归并时是将x-1和y归并 22 } 23 printf("%d ",ans); 24 } 25 return 0; 26 } 27 int gui(int x) 28 { 29 if(E[x].gen==x) 30 return x; 31 int y=E[x].gen,z=gui(E[x].gen);//先回溯更新父节点和根节点的权 32 E[x].sum=E[y].sum+E[x].sum;//(a,b]和为sum1 (b,c]和为sum2 则(a,c]为sum1+sum2 33 return E[x].gen=z; 34 } 35 int bing(int x,int y,int z) 36 { 37 int bx=gui(x); 38 int by=gui(y); 39 if(bx==by) 40 { 41 if(E[y].sum-E[x].sum!=z) 42 return 1; 43 } 44 else 45 { 46 E[by].gen=bx; 47 E[by].sum=E[x].sum-E[y].sum+z;//向量加法 48 } 49 return 0; 50 }
E - Peculiar apple-tree CodeForces - 931D
题目大意;有一颗苹果树,有很多花(??我英语不好),然后第一朵在树跟,其他在树枝,每次每朵花会一个结果,然后同时往下掉p的花中,掉到同一朵花的时,偶数个的苹果会全部碰碎,奇数个的只剩一个。问一个人在第一朵花能捡到的苹果数量。
画图来理解就是看他们最后能不能掉到第一朵花,而怎么处理同时掉落呢,距离。用它们到第一距离就可以代表时间了。注意距离不是高度,比如高度3的话苹果掉到1,高度7的话的苹果掉到3,那高度3 的话与第一朵花的距离是1,高度7与第一朵花的距离是2。这样,然后就是一个并查集。然后看它们到第一朵花的距离,相同的就会碰到一起。
1 #include<stdio.h> 2 #include<string.h> 3 struct Apple{ 4 int gen,dis;//gen是这个苹果最后会掉到哪朵花 dis是这朵花到gen的距离 5 }A[101108]; 6 int book[101108]; 7 inline int gui(int x){ 8 if(A[x].gen==x) 9 return x; 10 return A[x].gen=gui(A[x].gen); 11 } 12 int main() 13 { 14 int n,i,p; 15 scanf("%d",&n); 16 for(i=1;i<=n;i++) 17 { 18 A[i].gen=i;//一开始苹果结在这个花这里 19 A[i].dis=0;//距离没得说就是0 20 } 21 for(i=2;i<=n;i++) 22 { 23 scanf("%d",&p); 24 A[gui(i)].gen=gui(p);//并查集,让它的gen为最后掉到的地方 25 A[i].dis=A[p].dis+1;//而它到gen的距离就是它下一个掉落的地方的距离+1 26 } 27 memset(book,0,sizeof(book)); 28 for(i=1;i<=n;i++)//从第一个苹果开始 29 if(gui(i)==1)//如果能掉到第一朵花 30 book[A[i].dis]++; 31 //因为苹果都是同时掉落,所有用距离来代表时间,如果到达gen的距离相同说明他们会碰到一起 32 //book就统计最终能到第一朵花的花的距离,看一下每个距离相同的有多少个 33 int ans=0; 34 for(i=0;i<n;i++) 35 ans+=book[i]%2;//最后对2取模,同时间如果有偶数个苹果碰到一起就全部销毁,奇数个只剩一个 36 printf("%d ",ans); 37 return 0; 38 }
以上是关于有点意思的并查集的主要内容,如果未能解决你的问题,请参考以下文章