splay模板,启发式合并(其实就是暴力插入)即可。
顺便吐槽时限,带垃圾回收而已……不至于最后一个点死活不让过吧?
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cctype> #include<queue> #define maxn 100020 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch==‘-‘) f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-‘0‘; ch=getchar(); } return num*f; } int CNT; struct Node{ int val,size,e[2],fa,num; }tree[maxn*10]; int tot; struct Splay{ int root; Splay(){root=0;} inline void update(int x){tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+1; } inline int iden(int x){ return x==tree[tree[x].fa].e[1]; } inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; } void rotate(int x){ int y=tree[x].fa; int r=tree[y].fa; int sony=iden(x); int sonr=iden(y); if(root==y) root=x; int b=tree[x].e[sony^1]; connect(b,y,sony); connect(y,x,sony^1); connect(x,r,sonr); update(y); update(x); } void splay(int pos,int to){ to=tree[to].fa; while(tree[pos].fa!=to){ if(tree[tree[pos].fa].fa==to) rotate(pos); else if(iden(pos)==iden(tree[pos].fa)){ rotate(tree[pos].fa); rotate(pos); } else{ rotate(pos); rotate(pos); } } } inline int create(int val,int num,int fa){ tree[++tot]=(Node){val,1,{0,0},fa,num}; return tot; } int build(int val,int num){ if(root==0){ root=create(val,num,0); return root; } int now=root; while(now){ tree[now].size++; int nxt=val<tree[now].val?0:1; if(tree[now].e[nxt]==0){ connect(create(val,num,now),now,nxt); update(now); return tot; } now=tree[now].e[nxt]; } } void insert(int val,int num){ int p=build(val,num); if(++CNT==50){ splay(p,root); CNT=0; } } int rank(int val){ if(tree[root].size<val) return -1; int now=root; while(1){ if(tree[tree[now].e[0]].size+1==val) return tree[now].num; if(tree[tree[now].e[0]].size>=val) now=tree[now].e[0]; else{ val-=tree[tree[now].e[0]].size+1; now=tree[now].e[1]; } } } }s[maxn]; void pushtree(int now,int x){ s[x].insert(tree[now].val,tree[now].num); if(tree[now].e[0]) pushtree(tree[now].e[0],x); if(tree[now].e[1]) pushtree(tree[now].e[1],x); } int father[maxn]; int w[maxn]; int ufind(int x){ if(father[x]!=x) father[x]=ufind(father[x]); return father[x]; } void unionn(int x,int y){ x=ufind(x); y=ufind(y); if(tree[s[x].root].size<tree[s[y].root].size) swap(x,y); pushtree(s[y].root,x); father[y]=x; } int main(){ int n=read(),m=read(); for(int i=1;i<=n;++i){ w[i]=read(); father[i]=i; s[i].insert(w[i],i); } for(int i=1;i<=m;++i){ int x=read(),y=read(); unionn(x,y); } int p=read(); for(int i=1;i<=p;++i){ char c[10]; scanf("%s",c); int x=read(),y=read(); if(c[0]==‘Q‘) printf("%d\n",s[ufind(x)].rank(y)); else unionn(x,y); } return 0; }