http://acm.hdu.edu.cn/showproblem.php?pid=1512
大约是个左偏树模拟大架裸题
分离出两mokey所在堆的根节点,改变key值后插入,合并两mokey
#include<cstdio> #include<algorithm> inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); return x; } const int maxn = 100007; struct Node { int ls,rs,dis,key; Node() {} Node(int _key,int _l,int _r,int _d) : ls(_l),rs(_r),dis(_d),key(_key) {} }tree[maxn]; int sta[maxn],n,q,father[maxn]; int find(int x) { if(x!=father[x])father[x]=find(father[x]); return father[x]; } int merge(int x,int y) { if(!x||!y)return x+y; if(tree[x].key<tree[y].key)std::swap(x,y); tree[x].rs=merge(y,tree[x].rs); if(tree[tree[x].ls].dis<tree[tree[x].rs].dis)std::swap(tree[x].ls,tree[x].rs); tree[x].dis=tree[tree[x].rs].dis+1; return x; } int main() { while(~scanf("%d",&n)) { for(int a,i=1;i<=n;++i) { a=read();father[i]=i; tree[i]=Node(a,0,0,0); } q=read(); for(int a,b;q;q--) { a=read(),b=read(); int fa=find(a),fb=find(b); if(fa==fb){puts("-1");continue;} a=merge(tree[fa].ls,tree[fa].rs); tree[fa]=Node(tree[fa].key>>1,0,0,0); b=merge(tree[fb].ls,tree[fb].rs); tree[fb]=Node(tree[fb].key>>1,0,0,0); a=merge(a,b); a=merge(a,merge(fa,fb)); father[fa]=father[fb]=father[a]=a; printf("%d ",tree[a].key); } } return 0; }