题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123
题意:
思路:总的来说,查询区间第K小利用函数式线段树的减法操作。对于两棵树的合并,将节点少的树暴力插入到节点大的树上面。对于本题,首先,将输入的权值离散化,为已经给出的边建立函数式线段树。对于合并x,y,将y的父节点设为x,然后重新建立y为根的子树的函数式线段树。对于查询x,y,k,设其LCA为p,p的父节点为q,则x+y-p-q就是整个区间。
struct node { int L,R,s; }; node tree[N*400]; int root[N],tot; int f[N][20],w[N],n,m,K,d[N],size[N]; vector<int> g[N]; int M; int b[N]; int build(int a,int b) { int k=++tot; tree[k].s=0; if(a==b) return k; int mid=(a+b)>>1; tree[k].L=build(a,mid); tree[k].R=build(mid+1,b); return k; } int insert(int c,int s,int a,int b) { int k=++tot; tree[k]=tree[c]; tree[k].s++; if(a==b) return k; int mid=(a+b)>>1; if(s<=mid) tree[k].L=insert(tree[c].L,s,a,mid); else tree[k].R=insert(tree[c].R,s,mid+1,b); return k; } int visit[N],X; void BFS(int u) { queue<int> Q; Q.push(u); int i,v; while(!Q.empty()) { u=Q.front(); Q.pop(); visit[u]=X; root[u]=insert(root[f[u][0]],w[u],0,M); for(i=1;i<20;i++) f[u][i]=f[f[u][i-1]][i-1]; FOR0(i,SZ(g[u])) { v=g[u][i]; if(visit[v]==X) continue; f[v][0]=u; d[v]=d[u]+1; Q.push(v); } } } int get(int x,int k) { int i; FOR0(i,20) if(k&(1<<i)) x=f[x][i]; return x; } int getLca(int x,int y) { if(d[x]>d[y]) swap(x,y); y=get(y,d[y]-d[x]); if(x==y) return x; int i; for(i=19;i>=0;i--) if(f[x][i]&&f[y][i]&&f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } return f[x][0]; } #define L(a) tree[tree[a].L].s int query(int a,int b,int c,int d,int k,int L,int R) { if(L==R) return L; int s=L(a)+L(b)-L(c)-L(d); int mid=(L+R)>>1; if(k<=s) return query(tree[a].L,tree[b].L,tree[c].L,tree[d].L,k,L,mid); return query(tree[a].R,tree[b].R,tree[c].R,tree[d].R,k-s,mid+1,R); } void go() { int x,y,k,p,last=0; char op[10]; int fx,fy; while(K--) { RD(op); if(op[0]=='Q') { RD(x,y,k); x^=last; y^=last; k^=last; p=getLca(x,y); last=b[query(root[x],root[y],root[p],root[f[p][0]],k,0,M)]; PR(last); } else { RD(x,y); x^=last; y^=last; fx=get(x,d[x]); fy=get(y,d[y]); g[x].pb(y); g[y].pb(x); X++; if(size[fx]>=size[fy]) { size[fx]+=size[fy]; f[y][0]=x; d[y]=d[x]+1; visit[x]=X; BFS(y); } else { size[fy]+=size[fx]; f[x][0]=y; d[x]=d[y]+1; visit[y]=X; BFS(x); } } } } int main() { int CC; RD(CC); RD(n,m,K); int i,j,u,v; FOR1(i,n) RD(w[i]),size[i]=1,b[i]=w[i]; sort(b+1,b+n+1); M=unique(b+1,b+n+1)-(b+1); FOR1(i,n) w[i]=lower_bound(b+1,b+M+1,w[i])-b; tot=0; root[0]=build(0,M); FOR1(i,m) { RD(u,v); g[u].pb(v); g[v].pb(u); } FOR1(i,n) f[i][0]=-1; FOR1(i,n) if(f[i][0]==-1) { f[i][0]=0; d[i]=0; X++; BFS(i); } go(); }