当前位置 : 主页 > 编程语言 > c++ >

【模板】树链剖分

来源:互联网 收集:自由互联 发布时间:2021-06-23
1 #includebits/stdc++.h 2 using namespace std; 3 const int N=2e5+ 8 ; 4 int modd,n,m,rt,cnt= 0 ,cnto= 0 ; 5 int son[N],id[N],top[N],f[N],dep[N],siz[N],h[N 1 ],w[N],wt[N]; 6 struct edge{ 7 int to,nex; 8 }e[N]; 9 struct tree{ 10 int sum,lazy;
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=2e5+8;
  4 int modd,n,m,rt,cnt=0,cnto=0;
  5 int son[N],id[N],top[N],f[N],dep[N],siz[N],h[N<<1],w[N],wt[N];
  6 struct edge{
  7     int to,nex;
  8 }e[N];
  9 struct tree{
 10     int sum,lazy;
 11 }tr[N<<2];
 12 void add(int x,int y){
 13     e[++cnt]=(edge){y,h[x]};
 14     h[x]=cnt;
 15 }
 16 void dfs1(int u,int fa,int deep){
 17     dep[u]=deep;
 18     f[u]=fa;
 19     siz[u]=1;
 20     int maxson=-1;
 21     for(int i=h[u];i;i=e[i].nex){
 22         int v=e[i].to;
 23         if(v==fa) continue;
 24         dfs1(v,u,deep+1);
 25         siz[u]+=siz[v];
 26         if(siz[v]>maxson){
 27             son[u]=v;
 28             maxson=siz[v];
 29         }
 30     }
 31 }
 32 void dfs2(int u,int topfa){
 33     id[u]=++cnto;
 34     wt[cnto]=w[u];
 35     top[u]=topfa;
 36     if(!son[u]) return;
 37     dfs2(son[u],topfa);
 38     for(int i=h[u];i;i=e[i].nex){
 39         int v=e[i].to;
 40         if(v==f[u]||v==son[u]) continue;
 41         dfs2(v,v);
 42     }
 43 }
 44 //线段树下
 45 void build(int o,int l,int r){
 46     if(l==r){
 47         tr[o].sum=wt[l];
 48         if(tr[o].sum>modd) tr[o].sum%=modd;
 49         return;
 50     }
 51     int m=(l+r)>>1;
 52     build(o<<1,l,m);
 53     build(o<<1|1,m+1,r);
 54     tr[o].sum=(tr[o<<1].sum+tr[o<<1|1].sum)%modd;
 55 }
 56 void push_down(int o,int len){
 57     tr[o<<1].lazy+=tr[o].lazy;
 58     tr[o<<1|1].lazy+=tr[o].lazy;
 59     tr[o<<1].sum+=tr[o].lazy*(len+1>>1);
 60     tr[o<<1|1].sum+=tr[o].lazy*(len>>1);
 61     if(tr[o<<1].sum>=modd) tr[o<<1].sum%=modd;
 62     if(tr[o<<1|1].sum>=modd) tr[o<<1|1].sum%=modd;
 63     tr[o].lazy=0;
 64 }
 65 int query(int o,int l,int r,int x,int y){
 66     if(x<=l && r<=y) return tr[o].sum%modd;
 67     if(tr[o].lazy) push_down(o,r-l+1);
 68     int m=(l+r)>>1;
 69     int ans=0;
 70     if(x<=m) ans+=query(o<<1,l,m,x,y);
 71     if(y>m) ans+=query(o<<1|1,m+1,r,x,y);
 72     return ans%modd;
 73 }
 74 void change(int o,int l,int r,int x,int y,int k){
 75     if(x<=l && r<=y){
 76         tr[o].lazy+=k;
 77         tr[o].sum+=k*(r-l+1);
 78         return;
 79     }
 80     int m=(l+r)>>1;
 81     if(tr[o].lazy) push_down(o,r-l+1);
 82     if(x<=m) change(o<<1,l,m,x,y,k);
 83     if(y>m) change(o<<1|1,m+1,r,x,y,k);
 84     tr[o].sum=(tr[o<<1].sum+tr[o<<1|1].sum)%modd;
 85 }
 86 //线段树上
 87 //树链下
 88 int qSon(int u){
 89     return query(1,1,n,id[u],id[u]+siz[u]-1);
 90 }
 91 int qRange(int u,int v){
 92     int ans=0;
 93     while(top[u]!=top[v]){
 94         if(dep[top[u]]<dep[top[v]]) swap(u,v);
 95         ans+=query(1,1,n,id[top[u]],id[u]);
 96         ans%=modd;
 97         u=f[top[u]];
 98     }
 99     if(dep[u]>dep[v]) swap(u,v);
100     ans+=query(1,1,n,id[u],id[v]);
101     return ans%modd;
102 }
103 void updSon(int u,int k){
104     change(1,1,n,id[u],id[u]+siz[u]-1,k);
105 }
106 void updRange(int u,int v,int k){
107     k%=modd;
108     while(top[u]!=top[v]){
109         if(dep[top[u]]<dep[top[v]]) swap(u,v);
110         change(1,1,n,id[top[u]],id[u],k);
111         u=f[top[u]];
112     }
113     if(dep[u]>dep[v]) swap(u,v);
114     change(1,1,n,id[u],id[v],k);
115 }
116 //树链上
117 int main(){
118     memset(h,0,sizeof(h));
119     memset(son,0,sizeof(son));
120     scanf("%d%d%d%d",&n,&m,&rt,&modd);
121     for(int i=1;i<=n;++i) scanf("%d",&w[i]);
122     for(int i=1;i<n;++i){
123         int x,y;scanf("%d%d",&x,&y);
124         add(x,y);add(y,x);
125     }
126     dfs1(rt,0,1);
127     dfs2(rt,rt);
128     build(1,1,n);
129     while(m--){
130         int op,x,y,z;
131         scanf("%d",&op);
132         if(op==1){
133             scanf("%d%d%d",&x,&y,&z);
134             updRange(x,y,z);
135         }
136         else if(op==2){
137             scanf("%d%d",&x,&y);
138             printf("%d\n",qRange(x,y));
139         }
140         else if(op==3){
141             scanf("%d%d",&x,&y);
142             updSon(x,y);
143         }
144         else if(op==4){
145             scanf("%d",&x);
146             printf("%d\n",qSon(x));
147         }
148     }
149     return 0;
150 }
View Code
网友评论