BZOJ - 3123 森林 (可持久化线段树+启发式合并)
先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树。当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组。树的结点数可以用并查集来维护。总复杂度$O(nlog^2n)$。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,inf=0x3f3f3f3f; 5 int a[N],b[N],n2,hd[N],ne,n,m,nq,fa[N][20],dep[N],siz[N],fa2[N],rt[N],ls[N*100],rs[N*100],val[N*100],tot,vis[N]; 6 struct E {int v,nxt;} e[N<<1]; 7 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;} 8 int fd(int x) {return ~fa2[x]?fa2[x]=fd(fa2[x]):x;} 9 int mgg(int x,int y) { 10 int fx=fd(x),fy=fd(y); 11 if(fx==fy)return 0; 12 fa2[fx]=fy,siz[fy]+=siz[fx]; 13 return 1; 14 } 15 #define mid ((l+r)>>1) 16 int lca(int u,int v) { 17 if(dep[u]<dep[v])swap(u,v); 18 for(int i=19; i>=0&&dep[u]>dep[v]; --i)if(dep[fa[u][i]]>=dep[v])u=fa[u][i]; 19 if(u==v)return u; 20 for(int i=19; i>=0; --i)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i]; 21 return fa[u][0]; 22 } 23 void upd(int& u,int v,int x,int l=1,int r=n2) { 24 if(!u)u=++tot; 25 val[u]=val[v]+1; 26 if(l==r)return; 27 if(x<=mid)upd(ls[u],ls[v],x,l,mid),rs[u]=rs[v]; 28 else upd(rs[u],rs[v],x,mid+1,r),ls[u]=ls[v]; 29 } 30 int qry(int u,int v,int w1,int w2,int k,int l=1,int r=n2) { 31 if(l==r)return l; 32 int cnt=val[ls[u]]+val[ls[v]]-val[ls[w1]]-val[ls[w2]]; 33 return k<=cnt?qry(ls[u],ls[v],ls[w1],ls[w2],k,l,mid):qry(rs[u],rs[v],rs[w1],rs[w2],k-cnt,mid+1,r); 34 } 35 void dfs(int u,int f,int d,int flag) { 36 if(flag&&vis[u])return; 37 vis[u]=1; 38 fa[u][0]=f,dep[u]=d,rt[u]=0,upd(rt[u],rt[f],a[u]); 39 for(int i=1; i<20; ++i)fa[u][i]=fa[fa[u][i-1]][i-1]; 40 for(int i=hd[u]; ~i; i=e[i].nxt) { 41 int v=e[i].v; 42 if(v==f)continue; 43 dfs(v,u,d+1,flag); 44 } 45 } 46 void mg(int u,int v) { 47 if(siz[fd(u)]>siz[fd(v)])swap(u,v); 48 addedge(u,v),addedge(v,u),mgg(u,v),dfs(u,v,dep[v]+1,0); 49 } 50 int main() { 51 scanf("%*d"); 52 memset(hd,-1,sizeof hd),ne=0; 53 memset(fa2,-1,sizeof fa2); 54 scanf("%d%d%d",&n,&m,&nq); 55 for(int i=1; i<=n; ++i)scanf("%d",&a[i]); 56 for(int i=1; i<=n; ++i)b[i-1]=a[i]; 57 sort(b,b+n),n2=unique(b,b+n)-b; 58 for(int i=1; i<=n; ++i)a[i]=lower_bound(b,b+n2,a[i])-b+1; 59 for(int i=1; i<=n; ++i)siz[i]=1; 60 while(m--) { 61 int u,v; 62 scanf("%d%d",&u,&v); 63 addedge(u,v),addedge(v,u),mgg(u,v); 64 } 65 for(int i=1; i<=n; ++i)dfs(i,0,1,1); 66 for(int last=0; nq--;) { 67 char ch; 68 int u,v,k; 69 scanf(" %c",&ch); 70 if(ch=='Q') { 71 scanf("%d%d%d",&u,&v,&k),u^=last,v^=last,k^=last; 72 int w=lca(u,v),ans=b[qry(rt[u],rt[v],rt[w],rt[fa[w][0]],k)-1]; 73 printf("%d\n",ans),last=ans; 74 } else { 75 scanf("%d%d",&u,&v),u^=last,v^=last; 76 mg(u,v); 77 } 78 } 79 return 0; 80 }