【描述】
【思路】
首先如果没有2操作,我们可以使用主席树轻松完成,这就是count on a tree。考虑2操作,我们要合并两棵树。这时我们可以利用启发式合并。每次暴力把小的一棵树搜索一次,同时加入大的一棵树的主席树中,同时更新倍增维护LCA。这样就实现了合并。对于每一个点,这样的合并不会超过
次。所以时间复杂度和空间复杂度都是
。
代码:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define re register
using namespace std;
const int N=1e5+5;
tr1::unordered_map<int,int>lsr;
inline int red(){
int data=0;bool w=0; char ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=1,ch=getchar();
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return w?-data:data;
}
int n,las=0,cnt=0,q,m,a,b[N],c,dep[N],fa[N][17],sz[N],col[N],siz[N*205|1],rt[N],to[N<<1|1],f[N],nxp[N<<1|1],tot=0,ch[N*205|1][2],val[N];
inline int copy(int v){int u=++tot;ch[u][0]=ch[v][0];ch[u][1]=ch[v][1];siz[u]=siz[v];return tot;}
inline void add(int&u,int v,int l,int r,int w){
u=copy(v);++siz[u];
if(l==r)return;int mid=(l+r)>>1;
if(w<=mid)add(ch[u][0],ch[v][0],l,mid,w);
else add(ch[u][1],ch[v][1],mid+1,r,w);
}
inline int query(int u,int v,int l1,int l2,int l,int r,int k){
if(l==r)return l;int mid=(l+r)>>1,size=siz[ch[u][0]]+siz[ch[v][0]]-siz[ch[l1][0]]-siz[ch[l2][0]];
if(size>=k)return query(ch[u][0],ch[v][0],ch[l1][0],ch[l2][0],l,mid,k);
else return query(ch[u][1],ch[v][1],ch[l1][1],ch[l2][1],mid+1,r,k-size);
}
void dfs(int u,int ff,const int&cl){
dep[u]=dep[ff]+1;fa[u][0]=ff;col[u]=cl;
add(rt[u],rt[ff],1,n,lsr[val[u]]);
for(int re i=1;i<17;++i)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int re i=f[u];i;i=nxp[i])
if(to[i]!=ff)dfs(to[i],u,cl);
}
inline void add(int u,int v){
to[++cnt]=v;nxp[cnt]=f[u];f[u]=cnt;
to[++cnt]=u;nxp[cnt]=f[v];f[v]=cnt;
if(sz[col[u]]<sz[col[v]])u^=v^=u^=v;
sz[col[u]]+=sz[col[v]];
dfs(v,u,col[u]);
}
inline int lca(int u,int v){
if(dep[u]<dep[v])u^=v^=u^=v;
int t=dep[u]-dep[v];
for(int re i=0;(1<<i)<=t;++i)
if(t&(1<<i))u=fa[u][i];
if(u==v)return u;
for(int re i=16;~i;--i)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}char s[5];
int main(){red();
n=red();m=red();q=red();
for(int re i=1;i<=n;i++)b[i]=val[i]=red();
sort(b+1,b+n+1);int all=unique(b+1,b+n+1)-b-1;
for(int re i=1;i<=all;i++)lsr[b[i]]=i;
for(int re i=1;i<=n;i++)add(rt[i],0,1,n,lsr[val[i]]),dep[i]=1,col[i]=i,sz[i]=1;
for(int re i=1;i<=m;i++)add(red(),red());
while(q--){
scanf("%s",s);int u=red()^las,v=red()^las;
if(s[0]=='Q'){int lc=lca(u,v);
cout<<(las=b[query(rt[u],rt[v],rt[lc],rt[fa[lc][0]],1,n,red()^las)])<<"\n";
}else add(u,v);
}
}