Analysis
我都忘了自己学过左偏树了【呜呜呜呜】
就当模板复习吧
合并操作
int merge(int x,int y){
if(!x||!y) return x+y;
if(tree[x].val<tree[y].val) swap(x,y);//这里处理的是大根堆
tree[x].rc=merge(tree[x].rc,y);
fa[tree[x].rc]=x;//注意更新fa
if(tree[tree[x].lc].dep<tree[tree[x].rc].dep) swap(tree[x].lc,tree[x].rc);
if(tree[x].rc) tree[x].dep=tree[tree[x].rc].dep+1;//斜深度定义为根到右儿子的步数
else tree[x].dep=0;
return x;
}
寻找堆顶
int find(int x){
int rt=x;
while(rt!=fa[rt]) rt=fa[rt];
int f=fa[x];
while(f!=rt){
fa[x]=rt;
x=f;
f=fa[x];//有点像并查集的路径压缩
}
return rt;
}
弹出堆顶,并且将剩下的部分合并
int pop(int x){//先确定x为当前堆顶
int l=tree[x].lc;
int r=tree[x].rc;
fa[l]=l;fa[r]=r;
tree[x].lc=tree[x].rc=tree[x].dep=0;
return merge(l,r);
}
Code
完整代码
#include<bits/stdc++.h>
#define re register
#define in read()
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?(exit(0),EOF):*p1++;
}
inline int read(){
char ch;int f=1,res=0;
while((ch=nc())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+(ch^48);
ch=nc();
}
return f==1?res:-res;
}
const int N=100009;
struct node{
int lc,rc,dep,val;
}tree[N];
int fa[N];
int merge(int x,int y){
if(!x||!y) return x+y;
if(tree[x].val<tree[y].val) swap(x,y);
tree[x].rc=merge(tree[x].rc,y);
fa[tree[x].rc]=x;///
if(tree[tree[x].lc].dep<tree[tree[x].rc].dep) swap(tree[x].lc,tree[x].rc);
if(tree[x].rc) tree[x].dep=tree[tree[x].rc].dep+1;
else tree[x].dep=0;
return x;
}
int find(int x){
int rt=x;
while(rt!=fa[rt]) rt=fa[rt];
int f=fa[x];
while(f!=rt){
fa[x]=rt;
x=f;
f=fa[x];
}
return rt;
}
int pop(int x){
int l=tree[x].lc;
int r=tree[x].rc;
fa[l]=l;fa[r]=r;
tree[x].lc=tree[x].rc=tree[x].dep=0;
return merge(l,r);
}
int main(){
// freopen("data.in","r",stdin);
int n,m;
while((n=in)!=EOF){
memset(tree,0,sizeof(tree));
for(re int i=1;i<=n;++i) {
tree[i].val=in;
fa[i]=i;
}
m=in;
for(re int i=1;i<=m;++i){
int x=in,y=in;
int fx=find(x),fy=find(y);
if(fx==fy){printf("-1\n");continue;}
int X=pop(fx);
tree[fx].val/=2;
X=merge(X,fx);
int Y=pop(fy);
tree[fy].val/=2;
Y=merge(Y,fy);
printf("%d\n",tree[merge(X,Y)].val);
}
}
return 0;
}