主席树+启发式合并(LT) BZOJ3123
好久没做题了,写道SBT又RE又T
查询:主席树裸题。
修改:对于两个树合并重建小的树。
注意fa[x][i]重新计算时要清空
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> using namespace std; inline int read() { char c=getchar();int x=0,sig=1; for(;!isdigit(c);c=getchar()) if(c=='-') sig=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*sig; } inline void print(int x) { int buf[10],l=0; if(!x) l++; while(x) buf[++l]=x%10,x/=10; for(;l;l--) putchar(buf[l]+'0'); putchar('\n'); } const int maxn=80010; const int maxnode=10000010; int ls[maxnode],rs[maxnode],s[maxnode],ToT; void update(int& y,int x,int l,int r,int pos) { s[y=++ToT]=s[x]+1;if(l==r) return; int mid=l+r>>1;ls[y]=ls[x];rs[y]=rs[x]; if(pos<=mid) update(ls[y],ls[x],l,mid,pos); else update(rs[y],rs[x],mid+1,r,pos); } int query(int x1,int x2,int y1,int y2,int l,int r,int k) { if(l==r) return l; int mid=l+r>>1,k2=s[ls[y1]]+s[ls[y2]]-s[ls[x1]]-s[ls[x2]]; if(k<=k2) return query(ls[x1],ls[x2],ls[y1],ls[y2],l,mid,k); return query(rs[x1],rs[x2],rs[y1],rs[y2],mid+1,r,k-k2); } int n,m,q,val[maxn],tmp[maxn],root[maxn],lastans; int first[maxn],next[maxn*2],to[maxn*2],e,fa[maxn][20],dep[maxn]; int pa[maxn],sz[maxn]; void AddEdge(int a,int b) { to[++e]=b;next[e]=first[a];first[a]=e; to[++e]=a;next[e]=first[b];first[b]=e; } void dfs(int x,int f) { dep[x]=dep[fa[x][0]=f]+1;update(root[x],root[f],1,n,val[x]); sz[pa[x]]++; for(int i=1;i<17;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=first[x];i;i=next[i]) if(to[i]!=f) pa[to[i]]=pa[x],dfs(to[i],x); } int lca(int p,int q) { if(dep[p]<dep[q]) swap(p,q); for(int i=19;i>=0;i--) if((1<<i)<=dep[p]-dep[q]) p=fa[p][i]; for(int i=19;i>=0;i--) if(fa[p][i]!=fa[q][i]) p=fa[p][i],q=fa[q][i]; return p==q?p:fa[p][0]; } int main() { read();n=read();m=read();q=read(); for(int i=1;i<=n;i++) tmp[i]=val[i]=read(); sort(tmp+1,tmp+n+1); for(int i=1;i<=n;i++) val[i]=lower_bound(tmp+1,tmp+n+1,val[i])-tmp; for(int i=0;i<m;i++) AddEdge(read(),read()); for(int i=1;i<=n;i++) if(!fa[i][0]) pa[i]=i,dfs(i,0); for(int i=0;i<q;i++) { char tp=getchar(); while(!isalpha(tp)) tp=getchar(); if(tp=='Q') { int x=read()^lastans,y=read()^lastans,k=read()^lastans; int c=lca(x,y); print(lastans=tmp[query(root[c],root[fa[c][0]],root[x],root[y],1,n,k)]); } else { int u=read()^lastans,v=read()^lastans; int x=pa[u],y=pa[v]; if(sz[x]>sz[y]) swap(x,y),swap(u,v); pa[u]=y;AddEdge(u,v);dfs(u,v); } } return 0; }