主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree
题面: Count on a tree
题解:
主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y))-ans(father[LCA(X,Y)])
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=100000+50,maxm=maxn,maxlog=18; 7 int lastans=0,num_edge=0,edge_head[maxn],N,M,F[maxn][maxlog+2]; 8 int Dep[maxn],num_treenode=0,root[maxn],lsh_cnt=0,cor[maxn],U,V,K,X,Y; 9 inline int rd(){ 10 int x=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} 12 while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} 13 return f*x; 14 } 15 struct Edge{int to,nx;}edge[maxn<<1]; 16 inline void Add_edge(int from,int to){ 17 edge[++num_edge].nx=edge_head[from]; 18 edge[num_edge].to=to; 19 edge_head[from]=num_edge; 20 return; 21 } 22 struct Tree{int cnt,l,r,ls,rs;}t[(maxn<<3)+maxn*maxlog]; 23 inline void Build(int x,int l,int r){ 24 t[x].l=l;t[x].r=r;int mid=(l+r)>>1; 25 if(l==r)return; 26 Build(t[x].ls=++num_treenode,l,mid); 27 Build(t[x].rs=++num_treenode,mid+1,r); 28 return; 29 } 30 inline void Update(int u,int x,int s){ 31 int l=t[u].l,r=t[u].r,mid=(l+r)>>1; 32 t[x].l=l;t[x].r=r; 33 if(l==r&&l==s){t[x].cnt=t[u].cnt+1; return;} 34 if(s<=mid){t[x].rs=t[u].rs; Update(t[u].ls,t[x].ls=++num_treenode,s);} 35 else{t[x].ls=t[u].ls; Update(t[u].rs,t[x].rs=++num_treenode,s);} 36 t[x].cnt=t[t[x].ls].cnt+t[t[x].rs].cnt; 37 return; 38 } 39 struct A_{int yn,hn,id;}A[maxn]; 40 inline void Dfs(int x,int fa){ 41 Dep[x]=Dep[fa]+1; 42 F[x][0]=fa; 43 for(int i=1;i<=maxlog;i++) 44 F[x][i]=F[F[x][i-1]][i-1]; 45 Update(root[fa],root[x]=++num_treenode,A[x].hn); 46 for(int i=edge_head[x];i;i=edge[i].nx){ 47 int y=edge[i].to; 48 if(y==fa)continue; 49 Dfs(y,x); 50 } 51 return; 52 } 53 inline int LCA(int x,int y){ 54 if(Dep[x]<Dep[y])swap(x,y); 55 for(int i=maxlog;i>=0;i--){ 56 if(Dep[F[x][i]]>=Dep[y])x=F[x][i]; 57 if(x==y)return x; 58 } 59 for(int i=maxlog;i>=0;i--){ 60 if(F[x][i]!=F[y][i]){ 61 x=F[x][i];y=F[y][i]; 62 } 63 } 64 return F[x][0]; 65 } 66 inline bool cmp(const A_&a,const A_&b){return a.yn<b.yn;} 67 inline bool cmp2(const A_&a,const A_&b){return a.id<b.id;} 68 inline int Query(int u,int v,int z,int w,int k){ 69 int l=t[u].l,r=t[u].r; 70 if(l==r)return l; 71 int a=t[t[u].ls].cnt+t[t[v].ls].cnt-t[t[z].ls].cnt-t[t[w].ls].cnt; 72 if(a>=k)return Query(t[u].ls,t[v].ls,t[z].ls,t[w].ls,k); 73 else return Query(t[u].rs,t[v].rs,t[z].rs,t[w].rs,k-a); 74 } 75 int main(){ 76 N=rd();M=rd(); 77 for(int i=1;i<=N;i++)A[i].yn=rd(),A[i].id=i; 78 sort(A+1,A+N+1,cmp); 79 cor[A[1].hn=++lsh_cnt]=A[1].yn; 80 for(int i=2;i<=N;i++) 81 if(A[i-1].yn!=A[i].yn) 82 cor[A[i].hn=++lsh_cnt]=A[i].yn; 83 else A[i].hn=lsh_cnt; 84 sort(A+1,A+N+1,cmp2); 85 for(int i=1;i<N;i++){ 86 X=rd();Y=rd(); 87 Add_edge(X,Y);Add_edge(Y,X); 88 } 89 Build(root[0]=++num_treenode,1,lsh_cnt+5); 90 Dfs(1,0); 91 while(M--){ 92 U=rd();V=rd();K=rd(); 93 U^=lastans; 94 int lca=LCA(U,V); 95 lastans=Query(root[U],root[V],root[lca],root[F[lca][0]],K); 96 lastans=cor[lastans]; 97 if(M==0)printf("%d",lastans);else printf("%d\n",lastans); 98 } 99 return 0; 100 }
By:AlenaNuna