#include<bits/stdc++.h> #define MAXN 600005 using namespace std; int n,m,fa[MAXN],date,q; int num[MAXN],ch[MAXN][2],sz[MAXN],f[MAXN],cnt[MAXN],tot,zhuan[MAXN]; inline int read() { register int x=0,t=1; register char ch=getchar(); while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-'){t=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*t; } struct Splay{ int rt; int get(int x){ return (x==ch[f[x]][1]); } int up(int x){ sz[x] = cnt[x]; if(ch[x][0])sz[x] = sz[x]+sz[ch[x][0]]; if(ch[x][1])sz[x] = sz[x]+sz[ch[x][1]]; return 0; } int rote(int x){ int y = f[x],z = f[y],k = get(x),p = get(y); if(y==0)return 0; if(z)ch[z][p] = x; if(ch[x][k^1])f[ch[x][k^1]] = y; ch[y][k] = ch[x][k^1]; ch[x][k^1] = y; f[x] = z; f[y] = x; up(y);up(x); return 0; } int splay(int x){ for(int y = f[x];(y = f[x]);rote(x)){ rote((get(x)==get(y))?y:x); } rt = x; return 0; } int rank(int x){ int now=rt,ans=1; while(1){ if(num[now]<=x){ ans = ans+sz[ch[now][0]]; if(num[now]==x){ splay(now); return ans; } ans = ans+cnt[now]; now = ch[now][1]; } else{ now = ch[now][0]; } } } int pre(){//前继 比她小的最大 int now = ch[rt][0]; while(ch[now][1])now = ch[now][1]; return now; } int suc(){ int now = ch[rt][1]; while(ch[now][0])now = ch[now][0]; return now; } int add(int x,int js){ if(rt == 0){ tot++; zhuan[tot] = js; num[tot] = x; cnt[tot] = 1; sz[tot] = 1; rt = tot; return 0; } int now = rt; while(1){ if(num[now]==x){ cnt[now]++; splay(now); return 0; } int to = (num[now]<x); if(!ch[now][to]){ tot++; zhuan[tot] = js; ch[now][to] = tot; num[tot] = x; f[tot] = now; cnt[tot] = 1; sz[tot] = 1; splay(tot); return 0; } else now = ch[now][to]; } } int kth(int x){ int now =rt; while(1){ if(now==0)return (-1); if(sz[ch[now][0]]<x){ x = x-sz[ch[now][0]]; if(x<=cnt[now])return zhuan[now]; x = x-cnt[now]; now = ch[now][1]; } else{ now = ch[now][0]; } } } int del(int x){ rank(x); if(cnt[rt]>=2){ cnt[rt]--; sz[rt]--; return 0; } else{ if((!ch[rt][0])&&(!ch[rt][1])){ rt = 0; return 0; } if(ch[rt][0]&&(!ch[rt][1])){ f[ch[rt][0]] = 0; rt =ch[rt][0]; return 0; } if((!ch[rt][0])&&ch[rt][1]){ f[ch[rt][1]] = 0; rt =ch[rt][1]; return 0; } else{ splay(pre()); ch[rt][1] = ch[ch[rt][1]][1]; f[ch[rt][1]] = rt; up(rt); return 0; } } } }T[MAXN]; int mix(int zhu,int fu,int now){//主树编号 副树编号 副树的当前节点 if(ch[now][0])mix(zhu,fu,ch[now][0]); T[zhu].add(num[now],zhuan[now]); if(ch[now][1])mix(zhu,fu,ch[now][1]); } int found(int x){ if(fa[x]==x){ return x; } fa[x] = found(fa[x]); return fa[x]; } int main(){ n = read(); m = read(); for(int i=1;i<=n;i++){ date = read(); fa[i] = i; T[i].add(date,i); } for(int i=1;i<=m;i++){ int from,to; from = read(); to = read(); if(found(from)!=found(to)){//from跟to合并,其中to作为主树 mix(found(to),found(from),T[found(from)].rt); fa[found(from)] = found(to); } } cin>>q; for(int i=1;i<=q;i++){ char tp; int x,y; cin>>tp; x = read(); y = read(); if(tp=='B'){ if(found(x)!=found(y)){//from跟to合并,其中to作为主树 mix(found(y),found(x),T[found(x)].rt); fa[found(x)] = found(y); } } else{ printf("%d ",T[found(x)].kth(y)); } } }
一道很好的splay合并(暴力)模板题