标签:struct agg each which eve 更新 long ber 结合
5
20
16
10
10
4
5
2 3
3 4
3 5
4 5
1 5
8
5
5
-1
10
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int N=100003; 5 struct node{ 6 int w,l,r,fa,d; 7 }t[N]; 8 int find(int x){ 9 return x==t[x].fa?x:t[x].fa=find(t[x].fa); 10 } 11 int merge(int x,int y){//合并 12 if(!x||!y)return x+y;//有一个是空的树就直接返回另一个编号 13 if(t[x].w<t[y].w)swap(x,y);//由于维护的是大根堆所以左边比右边小要进行交换 14 t[x].r=merge(t[x].r,y);//右子树的根就是合并过后的编号 15 if(!t[x].l||t[t[x].l].d<t[t[x].r].d)swap(t[x].l,t[x].r);//如果左边根本就没有树或者是左边的路径长小于右边就要交换 16 t[x].d=t[t[x].l].d+t[t[x].r].d+1;//更新右子树路径的长度 17 return x;//返回新结合的根节点 18 } 19 int del(int x){ 20 int root=merge(t[x].l,t[x].r); 21 t[x].l=t[x].r=0; 22 return root; 23 } 24 int main () 25 { 26 int n;cin>>n; 27 for(int i=1;i<=n;i++){ 28 scanf("%d",&t[i].w); 29 t[i].fa=i; 30 } 31 cin>>n; 32 while(n--){ 33 int x,y; 34 scanf("%d%d",&x,&y); 35 x=find(x),y=find(y);//找出里面根,与维护并查集是一个道理 36 if(x==y){ 37 printf("-1\n"); continue; 38 } 39 //printf("%d\n",max(t[x].w,t[y].w)/2); 40 int a=del(x),b=del(y);//删除这两个代表性的值 41 t[x].w>>=1, t[y].w>>=1;//这两个猴子打完架之后除以2 42 int root=merge(a,b);//链接a,b 43 root=merge(root,x); root=merge(root,y);//合并一下树 44 t[x].fa=t[y].fa=t[root].fa=root;//更新他们的根节点的值 45 printf("%d\n",t[root].w); 46 } 47 return 0; 48 }
over
标签:struct agg each which eve 更新 long ber 结合
原文地址:https://www.cnblogs.com/saionjisekai/p/9715222.html