数据结构——树链剖分

Posted nelson992770019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构——树链剖分相关的知识,希望对你有一定的参考价值。

树链剖分——简单而强大的数据维护方法

只是放个板子而已。

用我的码风覆盖了的。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 //------------------------------------------------------
  4 inline int read(){
  5     int f=1,x=0;
  6     char c=getchar();
  7     while(!isdigit(c)){
  8         if(c==-) f=-1;
  9         c=getchar();
 10     } 
 11     while(isdigit(c)){
 12         x=x*10+c-0;
 13         c=getchar();
 14     } 
 15     return x*f;
 16 }
 17 //------------------------------------------------------
 18 const int N=2e5+10;
 19 int at[N<<1],sum[N<<1];
 20 int head[N],cnt,n,m,r,mod,tot,ans;
 21 int w[N],dep[N],siz[N],fa[N],son[N],top[N],id[N],w2[N];
 22 struct edge{ int to,next; }e[N<<1];
 23 inline void addedge(int from,int to){ e[++cnt]=(edge){to,head[from]};head[from]=cnt; }
 24 inline void add(int x,int y){addedge(x,y),addedge(y,x);}
 25 //-------------------------------------------------------
 26 void dfs1(int u,int f){
 27     dep[u]=dep[f]+1;
 28     siz[u]=1;
 29     fa[u]=f;
 30     int maxson=0;
 31     for(int i=head[u];i;i=e[i].next){
 32         int v=e[i].to;
 33         if(v==f) continue;
 34         dfs1(v,u);
 35         siz[u]+=siz[v];
 36         if(siz[v]>maxson) maxson=siz[v],son[u]=v;
 37     }
 38 }
 39 void dfs2(int u,int f){
 40     id[u]=++tot;
 41     w2[tot]=w[u];
 42     top[u]=f;
 43     if(!son[u]) return;
 44     dfs2(son[u],f);
 45     for(int i=head[u];i;i=e[i].next){
 46         int v=e[i].to;
 47         if(v==fa[u]||v==son[u]) continue;
 48         dfs2(v,v);
 49     }
 50 }
 51 //-------------------------------------------------------
 52 class Tree{
 53     private:
 54         inline int ls(int o){return o<<1;}
 55         inline int rs(int o){return o<<1|1;}
 56         inline void pushdown(int o,int l,int r){
 57             if(!at[o]) return;
 58             int mid=(l+r)>>1;
 59             sum[ls(o)]=(sum[ls(o)]+at[o]*(mid-l+1))%mod;
 60             sum[rs(o)]=(sum[rs(o)]+at[o]*(r-mid))%mod;
 61             at[ls(o)]=(at[ls(o)]+at[o])%mod;
 62             at[rs(o)]=(at[rs(o)]+at[o])%mod;
 63             at[o]=0;
 64         }
 65         inline void pushup(int o){ sum[o]=(sum[ls(o)]+sum[rs(o)])%mod;}
 66     public:
 67         void build(int o,int l,int r){
 68             if(l==r){
 69                 sum[o]=w2[l];
 70                 if(sum[o]>mod) sum[o]%=mod;
 71                 return;
 72             }
 73             int mid=(l+r)>>1;
 74             build(ls(o),l,mid);
 75             build(rs(o),mid+1,r);
 76             pushup(o);
 77         }
 78         void change(int o,int l,int r,int x,int y,int k){
 79             if(l>y||r<x) return;
 80             if(x<=l&&r<=y){
 81                 sum[o]+=(r-l+1)*k;
 82                 at[o]+=k;
 83                 return;
 84             }
 85             int mid=(l+r)>>1;
 86             pushdown(o,l,r);
 87             if(x<=mid) change(ls(o),l,mid,x,y,k);
 88             if(y>mid) change(rs(o),mid+1,r,x,y,k);
 89             pushup(o);
 90         }
 91         void query(int o,int l,int r,int x,int y){
 92             if(l>y||r<x) return;
 93             if(x<=l&&r<=y){
 94                 ans+=sum[o];
 95                 ans%=mod;
 96                 return;
 97             }
 98             int mid=(l+r)>>1;
 99             pushdown(o,l,r);
100             if(x<=mid) query(ls(o),l,mid,x,y);
101             if(y>mid) query(rs(o),mid+1,r,x,y);
102         }
103         inline int ask(int u,int v){
104             int cur=0;
105             while(top[u]!=top[v]){
106                 if(dep[top[u]]<dep[top[v]]) swap(u,v);
107                 ans=0;
108                 query(1,1,n,id[top[u]],id[u]);
109                 cur+=ans;
110                 cur%=mod;
111                 u=fa[top[u]];
112             }
113             ans=0;
114             if(dep[u]>dep[v]) swap(u,v);
115             query(1,1,n,id[u],id[v]);
116             cur+=ans;
117             return cur%mod;
118         }
119         inline void ask2(int u,int v,int k){
120             k%=mod;
121             while(top[u]!=top[v]){
122                 if(dep[top[u]]<dep[top[v]]) swap(u,v);
123                 change(1,1,n,id[top[u]],id[u],k);
124                 u=fa[top[u]];
125             }
126             if(dep[u]>dep[v]) swap(u,v);
127             change(1,1,n,id[u],id[v],k);
128         }    
129 }T;
130 //-------------------------------------------------------
131 int main(){
132     n=read();m=read();r=read();mod=read();
133     int k,x,y,z;
134     for(register int i=1;i<=n;i++) w[i]=read();
135     for(register int i=1;i<n;i++) add(read(),read());
136     dfs1(r,0);
137     dfs2(r,r);
138     T.build(1,1,n);
139     for(register int i=1;i<=m;i++){
140         k=read();
141         if(k==1){
142             x=read();y=read();z=read();
143             T.ask2(x,y,z);
144         }
145         else if(k==2){
146             x=read();y=read();
147             printf("%d
",T.ask(x,y));
148         }
149         else if(k==3){
150             x=read();z=read();
151             T.change(1,1,n,id[x],id[x]+siz[x]-1,z);
152         }
153         else{
154             x=read();ans=0;
155             T.query(1,1,n,id[x],id[x]+siz[x]-1);
156             printf("%d
",ans);
157         }
158     }
159     return 0;
160 } 

以上是关于数据结构——树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

树链剖分

树链剖分详解

树链剖分 入门

树链剖分(轻/重链剖分学习笔记)

树链剖分详解

学树链剖分记