先考虑对于一棵树进行路径查询,当然可以树链剖分,但没必要。
对于一个询问 [ x , y ] ,可以转化为 [ x , root ] + [ y , root ] - 2 [ lca , root ] + lca,即 [ x , root ] + [ y , root ] - [ lca , root ] - [ fa [ lca ] , root ]
所以只要统计节点到根节点的信息就可以了,求第k小,显然要用主席树。
我们知道,主席树的基本思想是前缀和,在序列上时,以前一个为pre;在树上时,只要以这个节点的父亲为pre就可以了。
这样就解决了询问。
对于连边,可以启发式合并。简而言之就是小树往大树上连。
启发式合并中,每个节点只有在当前size较小时才会被合并,每次合并后体积至少扩大为原来的两倍。所以总复杂度是O(NlogN)。因为更新倍增数组和插入是O(logN)的,所以带了两个log,还是可以接受的。
最后注意要离散化,数组要开大。
1 #include<cstdio> 2 #include<algorithm> 3 #include<string> 4 #include<cstring> 5 #include<cstdlib> 6 using namespace std; 7 8 int read(){ 9 int x=0;char ch=getchar(); 10 while(ch<'0'||ch>'9')ch=getchar(); 11 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 12 return x; 13 } 14 15 const int N=80005; 16 17 int testcase,n,m,t,ans=0; 18 char op[3]; 19 int x,y,k; 20 21 struct node{ 22 int y,nxt; 23 }e[N*4]; 24 int h[N],tot=0; 25 void ad(int x,int y){ 26 ++tot;e[tot].y=y;e[tot].nxt=h[x];h[x]=tot; 27 } 28 29 int fa[N]; 30 int find(int x){ 31 return x==fa[x]?x:fa[x]=find(fa[x]); 32 } 33 34 int root[N],cnt=0;; 35 int val[N],b[N],len; 36 struct Tree{ 37 int ls,rs,sz; 38 }tr[N*600]; 39 int build(int l,int r){ 40 int rt=++cnt; 41 tr[rt].sz=0; 42 if(l==r)return rt; 43 int mid=(l+r)>>1; 44 tr[rt].ls=build(l,mid); 45 tr[rt].rs=build(mid+1,r); 46 return rt; 47 } 48 int sz[N],st[N][18],dep[N],vis[N]; 49 int Hash(int x){ 50 return lower_bound(b+1,b+len+1,x)-b; 51 } 52 void insert(int &now,int pre,int l,int r,int x){ 53 now=++cnt; 54 tr[now]=tr[pre];++tr[now].sz; 55 if(l==r)return; 56 int mid=(l+r)>>1; 57 if(x<=mid)insert(tr[now].ls,tr[pre].ls,l,mid,x); 58 else insert(tr[now].rs,tr[pre].rs,mid+1,r,x); 59 } 60 void dfs(int x,int father,int rt){ 61 dep[x]=dep[father]+1; 62 st[x][0]=father;++sz[rt]; 63 vis[x]=1;fa[x]=father; 64 for(int j=1;j<=17;++j)st[x][j]=st[st[x][j-1]][j-1]; 65 insert(root[x],root[father],1,len,Hash(val[x])); 66 for(int i=h[x];i;i=e[i].nxt){ 67 int y=e[i].y; 68 if(y==father)continue; 69 dfs(y,x,rt); 70 } 71 } 72 int LCA(int x,int y){ 73 if(dep[x]<dep[y])swap(x,y); 74 for(int j=17;j>=0;--j)if(dep[st[x][j]]>=dep[y])x=st[x][j]; 75 if(x==y)return x; 76 for(int j=17;j>=0;--j){ 77 if(st[x][j]!=st[y][j])x=st[x][j],y=st[y][j]; 78 } 79 return st[x][0]; 80 } 81 int ask(int x,int y,int lca,int flca,int l,int r,int k){ 82 if(l==r)return b[l]; 83 int lsz=tr[tr[x].ls].sz+tr[tr[y].ls].sz-tr[tr[lca].ls].sz-tr[tr[flca].ls].sz; 84 int mid=(l+r)>>1; 85 if(k<=lsz)return ask(tr[x].ls,tr[y].ls,tr[lca].ls,tr[flca].ls,l,mid,k); 86 return ask(tr[x].rs,tr[y].rs,tr[lca].rs,tr[flca].rs,mid+1,r,k-lsz); 87 } 88 89 int main(){ 90 testcase=read();n=read();m=read();t=read(); 91 for(int i=1;i<=n;++i){ 92 val[i]=read();b[i]=val[i];fa[i]=i; 93 } 94 sort(b+1,b+n+1); 95 len=unique(b+1,b+n+1)-b-1; 96 while(m--){ 97 x=read();y=read(); 98 ad(x,y);ad(y,x); 99 } 100 root[0]=build(1,len); 101 for(int i=1;i<=n;++i){ 102 if(!vis[i])dfs(i,0,i),fa[i]=i; 103 } 104 while(t--){ 105 scanf("%s",op); 106 x=read();y=read(); 107 x^=ans,y^=ans; 108 if(op[0]=='L'){ 109 ad(x,y);ad(y,x); 110 int fx=find(x),fy=find(y); 111 if(sz[fx]>sz[fy]){ 112 swap(x,y);swap(fx,fy); 113 } 114 dfs(x,y,fy); 115 } 116 else { 117 k=read();k^=ans; 118 int lca=LCA(x,y); 119 ans=ask(root[x],root[y],root[lca],root[st[lca][0]],1,len,k); 120 printf("%d\n",ans); 121 } 122 } 123 }