这题splay启发式合并。。。也就是暴力插入。
然而为什么要写一个并查集?
不是为了找splay的根。。。只是为了判断是不是在一个集合内,不是就break掉。
5s作死啦。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define maxv 100500 using namespace std; int n,m,q,x,y,tree[maxv][3],size[maxv],fath[maxv],val[maxv],finds[maxv]; char s[5]; bool isroot(int x) { return tree[fath[x]][1]!=x&&tree[fath[x]][2]!=x; } void pushup(int x) { int ls=tree[x][1],rs=tree[x][2]; size[x]=size[ls]+size[rs]+1; } int getfather(int x) { if (x!=finds[x]) finds[x]=getfather(finds[x]); return finds[x]; } void insert(int node,int x,int now,int father) { if (now==0) { fath[node]=father; if (x>val[father]) tree[father][2]=node; else tree[father][1]=node; tree[node][1]=0;tree[node][2]=0; size[node]=1; return; } if (x>val[now]) insert(node,x,tree[now][2],now); else insert(node,x,tree[now][1],now); pushup(now); } void rotate(int x) { int y=fath[x],z=fath[y],l,r; if (tree[y][1]==x) l=1;else l=2; r=3-l; if (!isroot(y)) { if (tree[z][1]==y) tree[z][1]=x; else tree[z][2]=x; } fath[x]=z;fath[y]=x;fath[tree[x][r]]=y; tree[y][l]=tree[x][r];tree[x][r]=y; pushup(y);pushup(x); } void splay(int x) { while (!isroot(x)) { int y=fath[x],z=fath[y]; if (!isroot(y)) { if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x); else rotate(y); } rotate(x); } } void bfs(int x,int y) { queue <int> q; q.push(x); while (!q.empty()) { int head=q.front(); q.pop(); insert(head,val[head],y,y); if (tree[head][1]) q.push(tree[head][1]); if (tree[head][2]) q.push(tree[head][2]); } } void unionn(int x,int y) { int f1=getfather(x),f2=getfather(y); if (f1==f2) return; splay(x);splay(y); if (size[x]>size[y]) swap(x,y); bfs(x,y);finds[x]=y; } int ask(int now,int k) { int ls=tree[now][1],rs=tree[now][2]; if (size[ls]>=k) return ask(ls,k); else if (size[ls]<k-1) return ask(rs,k-size[ls]-1); else return now; } void work1() { scanf("%d%d",&x,&y); splay(x); if (size[x]<y) {printf("-1 ");return;} int ans=ask(x,y); printf("%d ",ans); splay(ans); } void work2() { scanf("%d%d",&x,&y); unionn(x,y); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&val[i]); size[i]=1; finds[i]=i; } for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); unionn(x,y); } scanf("%d",&q); for (int i=1;i<=q;i++) { scanf("%s",s); if (s[0]=='Q') work1(); else work2(); } return 0; }