bzoj2733
1.treap
每个点建一棵treap,维护优先级,然后启发式合并两棵treap
#include<cstdio> #include<cctype> #include<algorithm> #define maxn 100002 using namespace std; int rt[maxn],fa[maxn],n,m,q; struct data{int l,r,rnd,siz,key;data(){siz=1;l=r=rnd=0;}}tr[maxn]; int findfa(int x){if(fa[x]==x)return x;return fa[x]=findfa(fa[x]);} void read(int &x){ char ch=getchar();x=0;int f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } void rturn(int &x){int tmp=tr[x].l;tr[x].l=tr[tmp].r;tr[tmp].r=x;tr[tmp].siz=tr[x].siz;tr[x].siz=tr[tr[x].l].siz+1+tr[tr[x].r].siz;x=tmp;} void lturn(int &x){int tmp=tr[x].r;tr[x].r=tr[tmp].l;tr[tmp].l=x;tr[tmp].siz=tr[x].siz;tr[x].siz=tr[tr[x].l].siz+1+tr[tr[x].r].siz;x=tmp;} void insert(int &rt,int x){ if(!rt){rt=x;tr[x].rnd=rand();return;} tr[rt].siz++; if(tr[x].key<tr[rt].key){ insert(tr[rt].l,x); if(tr[tr[rt].l].rnd<tr[rt].rnd)rturn(rt); }else{ insert(tr[rt].r,x); if(tr[tr[rt].r],x); if(tr[tr[rt].r].rnd<tr[rt].rnd)lturn(rt); } } void merge_node(int x,int y){ if(!y)return; merge_node(x,tr[y].l); merge_node(x,tr[y].r); insert(x,y); } void merge(int x,int y){ int fx=findfa(x),fy=findfa(y); if(fx==fy)return; if(tr[fx].siz<tr[fy].siz)swap(fx,fy); fa[fy]=fx; merge_node(fx,fy); } int getkth(int x,int k){ if(k<=tr[tr[x].l].siz)return getkth(tr[x].l,k); k-=tr[tr[x].l].siz+1; if(k==0)return x; return getkth(tr[x].r,k); } int main(){ int a,b;tr[0].siz=0; read(n);read(m); for(int i=1;i<=n;i++)read(tr[i].key),fa[i]=i; for(int i=1;i<=m;i++){read(a);read(b);merge(a,b);} read(q); char cc; while(q--){ scanf(" %c",&cc);read(a);read(b); if(cc=='Q'){a=findfa(a);if(tr[a].siz<b)printf("-1\n");else printf("%d\n",getkth(a,b));}else merge(a,b); } }
2.splay
#include<cstdio> #include<cctype> #include<algorithm> #define maxn 100002 using namespace std; int n,m,q,rt[maxn],f[maxn],father[maxn],key[maxn],pos[maxn],siz[maxn],tr[maxn][2]; void read(int &x){ char ch=getchar();x=0;int f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } int findfa(int x){ if(f[x]==x)return x;return f[x]=findfa(f[x]); } inline void rotate(int x,int &rt){ int fa=father[x],gfa=father[fa];int whicx=(tr[fa][1]==x); if(fa==rt)rt=x; else tr[gfa][(tr[gfa][1]==fa)]=x; father[x]=gfa; father[fa]=x; tr[fa][whicx]=tr[x][whicx^1]; father[tr[x][whicx^1]]=fa; tr[x][whicx^1]=fa; siz[fa]=siz[tr[fa][0]]+siz[tr[fa][1]]+1; siz[x]=siz[tr[x][0]]+siz[tr[x][1]]+1; } void splay(int x,int &rt){ for(int y;y=father[x];rotate(x,rt)) if(father[y])rotate((x==tr[y][0])==(y==tr[father[y]][0])?y:x,rt); } void insert(int x,int &rt,int ff){ if(!rt){rt=x;father[x]=ff;return;} siz[rt]++; if(key[x]<key[rt])insert(x,tr[rt][0],rt); else insert(x,tr[rt][1],rt); } void merge_node(int x,int y){ if(!x)return; if(tr[x][0])merge_node(tr[x][0],y); if(tr[x][1])merge_node(tr[x][1],y); insert(x,rt[y],0); splay(x,rt[y]); } void merge(int a,int b){ int fta=findfa(a),ftb=findfa(b); if(fta==ftb)return; if(siz[rt[fta]]>siz[rt[ftb]])swap(fta,ftb); f[fta]=ftb; merge_node(rt[fta],ftb); } int query(int rt,int k){ int u=rt; while(1){ if(k<=siz[tr[u][0]])u=tr[u][0]; else if(siz[tr[u][0]]+1==k)return key[u]; else k-=siz[tr[u][0]]+1,u=tr[u][1]; } } int main(){ read(n);read(m); int a,b; for(int i=1;i<=n;i++){read(key[i]);pos[key[i]]=i;rt[i]=i;f[i]=i;siz[i]=1;} for(int i=1;i<=m;i++){read(a);read(b);merge(a,b);} int q;char ch;read(q); while(q--){ scanf(" %c",&ch);read(a);read(b); if(ch=='Q'){if(siz[rt[findfa(a)]]<b)printf("-1\n");else printf("%d\n",pos[query(rt[findfa(a)],b)]);} else merge(a,b); } }