bzoj 3123 森林
一开始图是森林 考虑树上两个节点间查询路径上k 大值 可维护两个节点到这棵树上根节点的权值线段树 这里可以使用可持久化思想 利用每一个点的父亲来维护这个点上的权值线段树
那么两者路径上的权值线段树 即 Tree[x]+Tree[y]-Tree[lca(x,y)]-Tree[fa[lca(x,y)]]; 所以询问的复杂度为 O(MlogN)
考虑合并 可使用启发式合并 。。很强 很暴力 合并复杂度 为 O(Nlog2N)
1 #include <bits/stdc++.h> 2 #define N 80010 3 #define M 26001000 4 using namespace std; 5 int T,siz,n,m,q,st[N],root[N],x,y,z; 6 int a[N],val[N],ee,vt; 7 struct node{ 8 int u,v,next; 9 }vs[N<<1]; 10 void vsadd(int u,int v) 11 { 12 vs[ee].u=u,vs[ee].v=v; 13 vs[ee].next=st[u];st[u]=ee++; 14 } 15 struct Seg 16 { 17 int l,r,sum; 18 }seg[M]; 19 void pushup(int rt) 20 { 21 seg[rt].sum=seg[seg[rt].l].sum+seg[seg[rt].r].sum; 22 } 23 void insert(int x,int &y,int l,int r,int v) 24 { 25 y=++siz;seg[y]=seg[x];seg[y].sum++; 26 if(l==r) return;int mid=(l+r)>>1; 27 if(v<=mid) insert(seg[x].l,seg[y].l,l,mid,v); 28 else insert(seg[x].r,seg[y].r,mid+1,r,v); 29 pushup(y); 30 } 31 int query(int a,int b,int c,int d,int l,int r,int kth) 32 { 33 if(l==r) return l;int mid=(l+r)>>1; 34 int tmp=seg[seg[a].l].sum+seg[seg[b].l].sum-seg[seg[c].l].sum-seg[seg[d].l].sum; 35 if(tmp<kth) return query(seg[a].r,seg[b].r,seg[c].r,seg[d].r,mid+1,r,kth-tmp); 36 else return query(seg[a].l,seg[b].l,seg[c].l,seg[d].l,l,mid,kth); 37 } 38 int dvsp[N],fa[N][25],ffa[N],size[N],sta[N],vp; 39 int find(int x) 40 { 41 if(x==ffa[x]) return x; 42 return ffa[x]=find(ffa[x]); 43 } 44 void dfs(int now,int ff) 45 { 46 insert(root[ff],root[now],1,vt,val[now]); 47 dvsp[now]=dvsp[ff]+1,fa[now][0]=ff; 48 for(int i=st[now];i!=-1;i=vs[i].next) 49 { 50 int v=vs[i].v; 51 if(v==ff) continue; 52 dfs(v,now);int fv=find(v),fnow=find(now); 53 if(size[fv]<size[fnow]) 54 ffa[fnow]=fv,size[fv]+=size[fnow]; 55 else ffa[fv]=fnow,size[fnow]+=size[fv]; 56 } 57 } 58 int lca(int x,int y) 59 { 60 if(dvsp[x]<dvsp[y])swap(x,y); 61 for(int i=20;i>=0;i--) if(dvsp[fa[x][i]]>=dvsp[y])x=fa[x][i]; 62 if(x==y)return x; 63 for(int i=20;i>=0;i--) if(dvsp[fa[x][i]]==dvsp[fa[y][i]]&&fa[x][i]!=fa[y][i]) 64 x=fa[x][i],y=fa[y][i]; 65 return fa[x][0]; 66 } 67 void Rebuild(int x,int ff) 68 { 69 sta[++vp]=x; 70 dvsp[x]=dvsp[ff]+1;fa[x][0]=ff; 71 insert(root[ff],root[x],1,vt,val[x]); 72 for (int i=st[x];i!=-1;i=vs[i].next) 73 if (vs[i].v!=ff) 74 Rebuild(vs[i].v,x); 75 } 76 void merge(int x,int y) 77 { 78 int fx=find(x),fy=find(y); 79 if (size[fx]>size[fy]) swap(x,y),swap(fx,fy); 80 vp=0; vsadd(x,y),vsadd(y,x); 81 Rebuild(x,y); 82 ffa[fx]=fy; 83 size[fy]+=size[fx]; 84 for (int i=1;i<=20;i++) 85 for (int j=1;j<=vp;j++) 86 fa[sta[j]][i]=fa[fa[sta[j]][i-1]][i-1]; 87 } 88 int Query(int x,int y,int z) 89 { 90 int Lca=lca(x,y); 91 return query(root[x],root[y],root[Lca],root[fa[Lca][0]],1,vt,z); 92 } 93 int lastans;char s[5]; 94 int main() 95 { 96 memset(st,-1,sizeof(st)); 97 scanf("%d",&T); 98 scanf("%d%d%d",&n,&m,&q); 99 for (int i=1;i<=n;i++)scanf("%d",&val[i]),a[i]=val[i]; 100 sort(a+1,a+n+1); 101 vt=unique(a+1,a+n+1)-a-1; 102 for (int i=1;i<=n;i++) val[i]=lower_bound(a+1,a+vt+1,val[i])-a; 103 for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),vsadd(x,y),vsadd(y,x); 104 for (int i=1;i<=n;i++) ffa[i]=i,size[i]=1; 105 for (int i=1;i<=n;i++) if(!root[i])dfs(i,0); 106 for (int i=1;i<=20;i++) 107 for (int j=1;j<=n;j++) 108 fa[j][i]=fa[fa[j][i-1]][i-1]; 109 for (int i=1;i<=q;i++) 110 { 111 scanf("%s",s); 112 if(s[0]=='Q') 113 { 114 scanf("%d%d%d",&x,&y,&z); 115 x^=lastans,y^=lastans,z^=lastans; 116 int ret=Query(x,y,z); 117 printf("%d ",a[ret]); 118 lastans=a[ret]; 119 } 120 else scanf("%d%d",&x,&y),x^=lastans,y^=lastans,merge(x,y); 121 } 122 }
还是太NAIVE了