主席树 || 可持久化线段树 || 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

posted @ 2019-03-06 22:05  AlenaNuna  阅读(109)  评论(0编辑  收藏  举报