最近总被各种奇怪的错误坑…
我写的是并查集+Treap启发式合并.
在启发式合并中任意一个节点最多被合并Θ(lg n)次,每次合并时间复杂度Θ(lg n),所以总的时间复杂度就是Θ((n+q)lg2n).
AC code:
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
const int N=100010;
int n,m,q;
int f[N];
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
}
struct nod{
int num,imp,size,fix;
nod *lc,*rc;
}pool[N],*pt[N],*NIL;
queue<nod*> Q;
void update(nod *p){
p->size=p->lc->size+p->rc->size+1;
}
nod* merge(nod *p1,nod *p2){
if(p1==NIL) return p2;
if(p2==NIL) return p1;
if(p1->fix>p2->fix){
p1->rc=merge(p1->rc,p2);
update(p1);
return p1;
}
p2->lc=merge(p1,p2->lc);
update(p2);
return p2;
}
void split(nod *p,nod *&p1,nod *&p2,int k){
if(p==NIL){
p1=p2=NIL;
return ;
}
if(p->lc->size+1>k){
split(p->lc,p1,p2,k);
p->lc=NIL;
update(p);
p2=merge(p2,p);
}
else{
split(p->rc,p1,p2,k-p->lc->size-1);
p->rc=NIL;
update(p);
p1=merge(p,p1);
}
}
int getrank(nod *p,int x){
if(p==NIL) return 0;
return p->imp>x?getrank(p->lc,x):getrank(p->rc,x)+p->lc->size+1;
}
void getkth(nod *p,int k){
if(k>p->size){
printf("-1\n");
return ;
}
nod *p1,*p2,*p3,*p4;
split(p,p1,p2,k-1);
split(p2,p3,p4,1);
printf("%d\n",p3->num);
p=merge(merge(p1,p3),p4);
}
nod* insert(nod *p,nod *q){
nod *p1,*p2;
split(p,p1,p2,getrank(p,q->imp));
p=merge(merge(p1,q),p2);
}
void DFS(nod *p){
if(p->lc!=NIL) DFS(p->lc);
if(p->rc!=NIL) DFS(p->rc);
p->size=1;p->lc=p->rc=NIL;
Q.push(p);
}
nod* combine(nod *p,nod *q){
if(p->size<q->size) {nod *t=p;p=q;q=t;}
DFS(q);
for(;!Q.empty();Q.pop()) p=insert(p,Q.front());
return p;
}
int main(){
NIL=&pool[0];
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
f[i]=i;
pt[i]=&pool[i];
scanf("%d",&pt[i]->imp);
pt[i]->num=i;pt[i]->size=1;pt[i]->fix=rand();pt[i]->lc=pt[i]->rc=NIL;
}
for(int i=1;i<=m;i++){
int a,b,fa,fb;
scanf("%d%d",&a,&b);
fa=find(a);fb=find(b);
if(fa==fb) continue;
f[fa]=fb;
pt[fb]=combine(pt[fa],pt[fb]);
}
scanf("%d",&q);
for(int i=1;i<=q;i++){
char s[13];
int x,y;
scanf("%s%d%d",&s,&x,&y);
if(s[0]=='Q') getkth(pt[find(x)],y);
else{
int fx=find(x),fy=find(y);
if(fx==fy) continue;
f[fx]=fy;
pt[fy]=combine(pt[fx],pt[fy]);
}
}
return 0;
}