树链剖分模板

Posted frankscode

tags:

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

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<vector>
  4 #define tx top[x]
  5 #define ty top[y]
  6 #define ls o<<1
  7 #define rs o<<1|1
  8 #define M ((L+R)>>1)
  9 using namespace std;
 10 const int maxn = 100010;
 11 
 12 int n, m, P ,root, tot;
 13 int A[maxn], fa[maxn], deep[maxn], num[maxn], son[maxn], ID[maxn], top[maxn], fID[maxn];
 14 int sumv[maxn*4],addv[maxn*4];
 15 vector<int> G[maxn];
 16 
 17 void addedge(int x,int y) {
 18     G[x].push_back(y);
 19 }
 20 
 21 int dfs1(int x,int dep) { //返回包括自己,子树的大小 
 22     deep[x] = dep;
 23     int ret = 1;
 24     int len = G[x].size();
 25     int MX = 0;
 26     for(int i = 0;i < len;i++) {
 27         int tp = G[x][i];
 28         if(fa[x] == tp) continue;
 29         fa[tp] = x;
 30         int back = dfs1(tp,dep+1);
 31         if(back > MX) {
 32             son[x] = tp;
 33             MX = back;    
 34         } 
 35         ret += back;
 36     }
 37     num[x] = ret;
 38     return ret;
 39 }
 40 
 41 void dfs2(int x) {
 42     if(x == 0) return;
 43     ID[x] = ++tot;
 44     fID[tot] = x;
 45     if(son[fa[x]] == x) top[x] = top[fa[x]];
 46     else top[x] = x; 
 47     int len = G[x].size();
 48     dfs2(son[x]);
 49     for(int i = 0;i < len;i++) {
 50         int tp = G[x][i];
 51         if(tp != fa[x] && tp != son[x]) dfs2(tp);
 52     }
 53 }
 54 
 55 inline void build(int o,int L,int R) {
 56     if(L == R) {
 57         sumv[o] = A[fID[L]]%P;
 58         return;
 59     }
 60     build(ls,L,M);
 61     build(rs,M+1,R);
 62     sumv[o] = (sumv[ls] + sumv[rs])%P;
 63 }
 64 
 65 inline void pushdown(int o,int L,int R) {
 66     (addv[ls] += addv[o])%=P;
 67     (addv[rs] += addv[o])%=P;
 68     (sumv[ls] += addv[o]*(M-L+1))%=P;
 69     (sumv[rs] += addv[o]*(R-M))%=P;
 70     addv[o] = 0;
 71 }
 72 
 73 int ql,qr,qa;
 74 inline void update(int o,int L,int R) {
 75     if(ql <= L && R <= qr) {
 76         (addv[o] += qa)%=P;
 77         (sumv[o] += qa*(R-L+1))%=P;
 78         return;
 79     }
 80     pushdown(o,L,R);
 81     if(ql <= M) update(ls,L,M);
 82     if(qr > M) update(rs,M+1,R);
 83     sumv[o] = (sumv[ls] + sumv[rs])%P;
 84 }
 85 
 86 inline int query(int o,int L,int R) {
 87     if(ql <= L && R <= qr) return sumv[o]%P;
 88     int ret = 0;
 89     pushdown(o,L,R);
 90     if(ql <= M) (ret += query(ls,L,M))%=P;
 91     if(qr > M) (ret += query(rs,M+1,R))%=P;
 92     return ret%P; 
 93 }
 94 
 95 
 96 int LCA(int x,int y) {
 97     int ret = 0;
 98     while(tx != ty) {
 99         if(deep[tx] >= deep[ty]) {
100             //x 走到 top[x](编号小) 的 爸爸 ,top[x] 的爸爸是轻链 
101             ql = ID[tx], qr = ID[x];//下闭上开 
102             (ret += query(1,1,n))%=P; 
103             x = fa[tx];    
104         }
105         else {
106             ql = ID[ty], qr = ID[y];
107             (ret += query(1,1,n))%=P;
108             y = fa[ty];    
109         }
110     }
111 
112     if(x == y) {
113         ql = ID[x],qr = ql;
114         (ret += query(1,1,n))%=P;
115         return ret;
116     }
117      if(deep[x] > deep[y]) swap(x,y);
118     ql = ID[x], qr = ID[y]; 
119      (ret += query(1,1,n))%=P;
120   return ret;
121 }
122 
123 void LCA_add(int x,int y,int k) {
124     qa = k%P;
125     while(tx != ty) {
126         if(deep[tx] >= deep[ty]) {
127             //x 走到 top[x](编号小) 的 爸爸 ,top[x] 的爸爸是轻链 
128             ql = ID[tx], qr = ID[x];//下闭上开 
129             update(1,1,n); 
130             x = fa[tx];    
131         }
132         else {
133             ql = ID[ty], qr = ID[y];
134             update(1,1,n);
135             y = fa[ty];    
136         }
137     }
138 
139     if(x == y) {
140         ql = ID[x],qr = ql;
141         update(1,1,n);
142         return;
143     }
144      if(deep[x] > deep[y]) swap(x,y);
145     ql = ID[x], qr = ID[y]; 
146      update(1,1,n);
147 }
148 
149 int main() {
150     scanf("%d %d %d %d",&n, &m, &root, &P);
151     for(int i = 1;i <= n;i++) scanf("%d",A+i);
152     for(int i = 1,x,y;i < n;i++) {
153         scanf("%d%d",&x,&y);
154         addedge(x,y);
155         addedge(y,x);
156     }
157 
158     dfs1(root,1);
159     dfs2(root);
160     build(1,1,n);
161 
162     for(int i = 1,x,l,r,z;i <= m;i++) {
163         scanf("%d",&x);
164         if(x == 1) {
165             scanf("%d%d%d",&l,&r,&z);
166             LCA_add(l,r,z);
167         } else if(x == 2) {
168             scanf("%d%d",&l,&r);
169             printf("%d
",LCA(l,r));
170         } else if(x == 3) {
171             scanf("%d%d",&l,&z);
172             ql = ID[l],qr = ql+num[l]-1,qa=z;
173             update(1,1,n);
174         } else {
175             scanf("%d",&z);
176             ql = ID[z],qr = ql + num[z]-1;
177             printf("%d
",query(1,1,n));
178         }
179     }
180     return 0;
181 } 

 

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

模板时间◆模板·II◆ 树链剖分

树链剖分模板题(luogu3384 模板树链剖分)

树链剖分模板

BZOJ 2243--染色(树链剖分)

模板树链剖分

luoguP3384 模板树链剖分