bzoj2733
对于操作B 就用并查集看是否已经联通,若未联通就把两棵splay合并..
两棵splay的合并,启发式合并?(其实就是暴力合并【捂脸】)
把个数少的往个数大的里面一个个插入…..
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 110000
int f[N],a[N],b[N],n,m,cnt=0,fa[N],size[N],ch[N][2],root[N],q,data[N];
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
void update(int p){size[p]=size[ch[p][0]]+size[ch[p][1]]+1;}
void rotate(int &x){
int y=fa[x],z=fa[y],t=ch[y][0]==x;
if(z) ch[z][ch[z][1]==y]=x;
fa[y]=x;fa[x]=z;fa[ch[x][t]]=y;
ch[y][t^1]=ch[x][t];ch[x][t]=y;
update(y);update(x);
}
void splay(int x){
while(fa[x]){
int y=fa[x];
if(!fa[y]){rotate(x);return;}
if(ch[y][0]==x^ch[fa[y]][0]==y) rotate(x);
else rotate(y);rotate(x);
}
}
void insert(int &p,int x,int ff){
if(!p){
p=x;fa[p]=ff;size[p]=1;ch[p][0]=ch[p][1]=0;splay(p);
return ;
}if(a[x]<a[p]) insert(ch[p][0],x,p);
else if(a[x]>a[p]) insert(ch[p][1],x,p);
}
void merge(int xx,int yy){
int x=find(xx),y=find(yy);
if(x==y) return;
if(size[root[x]]<size[root[y]]) swap(x,y);//y往x中插
int op=0,cl=1;data[1]=root[y];
while(op<cl){
int p=data[++op];
if(ch[p][0]) data[++cl]=ch[p][0];
if(ch[p][1]) data[++cl]=ch[p][1];
insert(root[x],p,0);root[x]=p;
}f[y]=x;
}
int query(int p,int x){
if(x>size[p]) return -1;
if(size[ch[p][0]]+1==x) return p;
if(x<=size[ch[p][0]]) return query(ch[p][0],x);
return query(ch[p][1],x-size[ch[p][0]]-1);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
f[i]=i;root[i]=i;
size[i]=1;fa[i]=ch[i][0]=ch[i][1]=0;
}
for(int i=1;i<=m;i++){
int x,y;scanf("%d%d",&x,&y);
merge(x,y);
}scanf("%d",&q);
for(int i=1;i<=q;i++){
char ch[5];int x,y;scanf("%s%d%d",ch,&x,&y);
if(ch[0]=='B') merge(x,y);
else printf("%d\n",query(root[find(x)],y));
}
return 0;
}