【题目地址】点击打开链接
【分析】
平衡树的启发式合并,可以证明是O(nlog2n)的。
【代码】
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define pf printf
#define MAXN 100010
struct SplayNode{
#define node SplayNode
node* ch[2];
node* fa;
int sz;
int val;
node(){
ch[0]=ch[1]=fa=NULL;
sz=val=0;
}
}*null=new node(),*point[MAXN],pool[MAXN],*New=pool;
int N,M,Q;
int hash[MAXN];
int fa[MAXN];
node* Get(int val){
New->ch[0]=New->ch[1]=New->fa=null;
New->sz=1;
New->val=val;
return New++;
}
int Getfa(int x){
return x==fa[x]?x:fa[x]=Getfa(fa[x]);
}
void Read(int& x){
char tt=getchar();
while(tt<'0'||'9'<tt) tt=getchar();
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
}
void Read(char& x){
x=getchar();
while(x!='B'&&x!='Q') x=getchar();
}
void Updata(node* r){
r->sz=1;
if(r->ch[0]!=null) r->sz+=r->ch[0]->sz;
if(r->ch[1]!=null) r->sz+=r->ch[1]->sz;
}
void Rotate(node* r,bool k){
node* t=r->fa;
t->ch[!k]=r->ch[k];
r->ch[k]->fa=t;
r->fa=t->fa;
if(t==t->fa->ch[0]) t->fa->ch[0]=r;
else t->fa->ch[1]=r;
t->fa=r;
r->ch[k]=t;
Updata(t);
Updata(r);
}
void Splay(node* r,node* f){
while(r->fa!=f){
if(r->fa->fa==f){
if(r==r->fa->ch[0]) Rotate(r,1);
else Rotate(r,0);
}
else{
node* a=r->fa;
node* b=a->fa;
if(a==b->ch[0]){
r==a->ch[0]?Rotate(a,1):Rotate(r,0);
Rotate(r,1);
}
else{
r==a->ch[1]?Rotate(a,0):Rotate(r,1);
Rotate(r,0);
}
}
}
}
void Insert(node* r,node* p){
if(p->val<r->val){
if(r->ch[0]==null)
r->ch[0]=p,p->fa=r;
else
Insert(r->ch[0],p);
}
else{
if(r->ch[1]==null)
r->ch[1]=p,p->fa=r;
else
Insert(r->ch[1],p);
}
Updata(r);
}
void Merge(node* u,node* v){
if(u->ch[0]!=null) Merge(u->ch[0],v);
if(u->ch[1]!=null) Merge(u->ch[1],v);
u->sz=1;
u->ch[0]=u->ch[1]=u->fa=null;
Insert(v,u);
}
void Addedge(int u,int v){
if(Getfa(u)==Getfa(v)) return;
fa[fa[u]]=fa[v];
Splay(point[u],null);
Splay(point[v],null);
if(point[u]->sz>point[v]->sz)
swap(u,v);
Merge(point[u],point[v]);
}
void Init(){
Read(N);
Read(M);
int tmp,u,v;
rep(i,1,N) fa[i]=i;
rep(i,1,N){
Read(tmp);
hash[tmp]=i;
point[i]=Get(tmp);
}
rep(i,1,M){
Read(u);
Read(v);
Addedge(u,v);
}
}
int Select(node* r,int k){
if(r->sz<k) return -1;
if(k==r->ch[0]->sz+1)
return hash[r->val];
else if(k<=r->ch[0]->sz)
return Select(r->ch[0],k);
else
return Select(r->ch[1],k-r->ch[0]->sz-1);
}
void Solve(){
Read(Q);
char Ch;
int u,v;
while(Q--){
Read(Ch);
Read(u);
Read(v);
if(Ch=='B'){
Addedge(u,v);
}
else{
Splay(point[u],null);
pf("%d\n",Select(point[u],v));
}
}
}
int main(){
Init();
Solve();
return 0;
}