BZOJ 3626 [LNOI2014]LCA在线+主席树+树剖

Posted Troy Ricardo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3626 [LNOI2014]LCA在线+主席树+树剖相关的知识,希望对你有一定的参考价值。

题目链接:

  TP

题解:

    可能是我比较纱布,看不懂题解,只好自己想了……

  我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案。

  首先LCA一定是z的祖先(这里说的祖先包括自己,以下祖先均为此概念)节点,也就是是说我们只要计算出每个祖先节点的贡献就可以了,再考虑每个祖先的贡献如何计算。

  我们发现对于深度其实是该点到root的路径点数,所以我们可以这样想,我们询问z的祖先的答案,就是在计算有对于给定区间有多少个点经过了z的祖先。

  那么思路到这里就很清晰了,我们先把每个点到root的路径上的点权都加1,在询问的时候用历史版本做差分即可,那么带永久化标记的主席树+树剖啊QwQ。

  至于时间复杂度,有理有据的$O(nlog^2)$。

代码:

  

  1 #define Troy 
  2 
  3 #include <bits/stdc++.h>
  4 
  5 using namespace std;
  6 
  7 inline int read(){
  8     int s=0,k=1;char ch=getchar();
  9     while(ch<0|ch>9)    ch==-?k=-1:0,ch=getchar();
 10     while(ch>47&ch<=9)    s=s*10+(ch^48),ch=getchar();
 11     return s*k;
 12 }
 13 
 14 const int N=5e4+5,mod=201314;
 15 
 16 int n,Q;
 17 
 18 struct edges{
 19     int v;edges *last;
 20 }edge[N<<1],*head[N];int cnt;
 21 
 22 inline void push(int u,int v){
 23     edge[++cnt]=(edges){v,head[u]};head[u]=edge+cnt;
 24 }
 25 
 26 class Persistent_Segment_tree{
 27 public:
 28     inline void add(int pos,int l,int r){
 29         add(root[pos-1],root[pos],1,n,l,r);
 30     }
 31     inline int query(int last,int pos,int l,int r){
 32         return query(root[last-1],root[pos],1,n,l,r,0);
 33     }
 34     inline void build(){
 35         root[0]=tree;
 36         root[0]->lc=tree;
 37         root[0]->rc=tree;
 38         cnt_tree=1;
 39     }
 40     inline int  out(){
 41         return cnt_tree;
 42     }
 43 private:
 44     struct Tree{
 45         Tree *lc,*rc;
 46         int sign_per,val;
 47         Tree(){sign_per=val=0;lc=rc=NULL;}
 48     }tree[N<<7],*root[N<<5];int cnt_tree;
 49     inline void add(Tree *p,Tree *&u,int l,int r,int x,int y){
 50         u=tree+cnt_tree;cnt_tree++;
 51         *u=*p;
 52         u->val+=y-x+1;
 53         u->val%=mod;
 54         if(x<=l&&r<=y){;u->sign_per++;return;}
 55         int mid=l+r>>1;
 56         if(x>mid)   add(p->rc,u->rc,mid+1,r,x,y);
 57         else    if(y<=mid)  add(p->lc,u->lc,l,mid,x,y);
 58         else    add(p->lc,u->lc,l,mid,x,mid),add(p->rc,u->rc,mid+1,r,mid+1,y);
 59     }
 60     inline int query(Tree *p,Tree *u,int l,int r,int x,int y,int sign_p){
 61         if(x<=l&&r<=y){
 62             return (sign_p*1ll*(r-l+1)%mod+u->val-p->val)%201314+mod;
 63         }
 64         int mid=l+r>>1,ret=0;
 65         if(y>mid)   ret+=query(p->rc,u->rc,mid+1,r,x,y,sign_p+u->sign_per-p->sign_per);
 66         if(x<=mid)  ret+=query(p->lc,u->lc,l,mid,x, y, sign_p+u->sign_per-p->sign_per);
 67         return ret%201314;
 68     }
 69 }war;
 70 
 71 int fa[N],g[N],size[N],heavy[N],tid[N],idx,deep[N],L[N],R[N];
 72 
 73 inline void dfs(int x){
 74     size[x]=1;
 75     for(edges *i=head[x];i;i=i->last)   if(i->v!=fa[x]){
 76         deep[i->v]=deep[x]+1,fa[i->v]=x,dfs(i->v);
 77         size[x]+=size[i->v];
 78         if(size[heavy[x]]<size[i->v])
 79             heavy[x]=i->v;
 80     }
 81 }
 82 
 83 inline void dfs(int x,int grand){
 84     tid[x]=++idx;
 85     g[x]=grand;
 86     if(heavy[x]){
 87         dfs(heavy[x],grand);
 88         for(edges *i=head[x];i;i=i->last)   if(i->v!=fa[x]&&i->v!=heavy[x]){
 89             dfs(i->v,i->v);
 90         }
 91     }
 92 }
 93 
 94 inline void add(int x){
 95     L[x]=idx+1;
 96     int t=x;
 97     while(g[x]!=1){
 98         ++idx;
 99         war.add(idx,tid[g[x]],tid[x]);
100         x=fa[g[x]];
101     }
102     ++idx,war.add(idx,tid[1],tid[x]);
103     R[t]=idx;
104 }
105 
106 inline int query(int x,int l,int r){
107     int ret=0;
108     while(g[x]!=1){
109         (ret+=war.query(L[l],R[r],tid[g[x]],tid[x]))%=mod;
110         x=fa[g[x]];
111     }        
112     ret+=war.query(L[l],R[r],tid[1],tid[x]);
113     return ret%mod;
114 }
115 
116 int main(){
117     n=read(),Q=read();
118     for(int i=2;i<=n;++i){
119         int x=read()+1;
120         push(x,i),push(i,x);
121     }
122     dfs(1);dfs(1,1);idx=0;
123     war.build();
124     for(int i=1;i<=n;++i){
125         add(i);
126     }
127     while(Q--){
128         int l=read()+1,r=read()+1,z=read()+1;
129         printf("%d\n",(query(z,l,r)%mod+mod)%mod);
130     }
131 }

 

以上是关于BZOJ 3626 [LNOI2014]LCA在线+主席树+树剖的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3626 [LNOI2014]LCA

Bzoj3626 [LNOI2014]LCA

BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

bzoj3626 [LNOI2014]LCA

BZOJ3626[LNOI2014]LCA 离线+树链剖分+线段树

bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)