• 主席树 || 可持久化线段树 || 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
    ",lastans);
     98     }
     99     return 0;
    100 }

    By:AlenaNuna

  • 相关阅读:
    Mysql数据库快速备份还原-mysqldump
    写给年轻人的交友和人脉建议
    令人担忧的趋势:科技崇拜与人文失落
    高情商的特征
    高情商与朋友圈
    数据库临时表空间设置
    oracle 临时表空间的增删改查
    语言表达能力写作能力决定一个人的发展和未来
    一个人如何从平庸到优秀,再到卓越?
    06.堆排序
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/10486462.html
Copyright © 2020-2023  润新知