洛谷 P3384 【模板】轻重链剖分

题目传送门

解题思路:

树链剖分的板子,写这篇博客只是为了存个代码.

AC代码:

  1 #include<iostream>
  2 #include<cstdio> 
  3 #include<cstring>
  4 
  5 using namespace std;
  6 
  7 int n,m,rr,p,a[100001],tot,head[100001],rk[100001];
  8 //rk[i]表示dfs中第i个被访问的点是哪个(或者说在线段树上第i号是谁),线段树赋值时有用 
  9 struct xianduanshu {
 10     int v,l,r,lazy;
 11 }e[400002];
 12 struct bian {
 13     int to,next;
 14 }c[200001];
 15 struct dian {
 16     int f,d,son,si,top,id;
 17 }q[100001];
 18 //父亲,相对于根的深度,重儿子,子树大小,链顶,编号(线段树上的) 
 19 
 20 inline void build(int rt,int L,int R) {//线段树建树 
 21     e[rt].l = L;e[rt].r = R;
 22     if(L == R) {
 23         e[rt].v = a[rk[L]] % p;
 24         return ;
 25     }
 26     int mid = L + R >> 1;
 27     build(rt * 2,L,mid);
 28     build(rt * 2 + 1,mid + 1,R);
 29     e[rt].v = (e[rt*2].v % p + e[rt*2+1].v % p) % p;
 30 }
 31 
 32 inline void add(int x,int y) {
 33     c[++tot].to = y;
 34     c[tot].next = head[x];
 35     head[x] = tot;
 36 }
 37 
 38 inline void dfs1(int u,int fa,int deep) {//找重儿子 
 39     q[u].d = deep;
 40     q[u].f = fa;
 41     q[u].si = 1;
 42     q[u].son = 0;
 43     for(int i = head[u];i; i = c[i].next) {
 44         int o = c[i].to;
 45         if(o == fa) continue;
 46         dfs1(o,u,deep + 1);
 47         q[u].si += q[o].si;
 48         if(q[q[u].son].si < q[o].si) q[u].son = o;
 49     }
 50 }
 51 
 52 inline void dfs2(int rt,int topf) {//找重链 
 53     q[rt].id = ++tot;
 54     rk[tot] = rt;
 55     q[rt].top = topf;
 56     if(q[rt].son == 0) return ;
 57     dfs2(q[rt].son,topf);//处理重链 
 58     for(int i = head[rt];i; i = c[i].next) {
 59         int o = c[i].to;
 60         if(o == q[rt].f || o == q[rt].son) continue;
 61         dfs2(o,o);//处理轻链 
 62     }
 63 }
 64 
 65 inline void pushdown(int rt) {
 66     if(e[rt].lazy) {
 67         e[rt*2].v = (e[rt*2].v + e[rt].lazy * (e[rt*2].r - e[rt*2].l + 1) % p) % p;
 68         e[rt*2+1].v = (e[rt*2+1].v + e[rt].lazy * (e[rt*2+1].r - e[rt*2+1].l + 1) % p) % p;
 69         e[rt*2].lazy = (e[rt*2].lazy + e[rt].lazy) % p;
 70         e[rt*2+1].lazy = (e[rt*2+1].lazy + e[rt].lazy) % p;
 71         e[rt].lazy = 0;
 72     }
 73 }
 74 
 75 inline void pl(int rt,int L,int R,int vv) {
 76     if(L <= e[rt].l && R >= e[rt].r) {
 77         e[rt].v = (e[rt].v + vv * (e[rt].r - e[rt].l + 1) % p) % p;
 78         e[rt].lazy = (e[rt].lazy + vv) % p;
 79         return ;
 80     }
 81     pushdown(rt);
 82     int mid = e[rt].l + e[rt].r >> 1;
 83     if(L <= mid) pl(rt * 2,L,R,vv);
 84     if(R > mid) pl(rt * 2 + 1,L,R,vv);
 85     e[rt].v = (e[rt*2].v % p + e[rt*2+1].v % p) % p;
 86 }
 87 
 88 inline void treeadd(int x,int y,int z) {//区间修改 
 89     int tx = q[x].top;
 90     int ty = q[y].top;
 91     while(tx != ty) {
 92         if(q[tx].d >= q[ty].d) {
 93             pl(1,q[tx].id,q[x].id,z);
 94             x = q[tx].f;tx = q[x].top;
 95         }
 96         else {
 97             pl(1,q[ty].id,q[y].id,z);
 98             y = q[ty].f;ty = q[y].top;
 99         }
100     }
101     if(q[x].d > q[y].d)
102         pl(1,q[y].id,q[x].id,z);
103     else
104         pl(1,q[x].id,q[y].id,z);
105 }
106 
107 inline int chaxun(int rt,int L,int R) {
108     long long uu = 0;
109     if(e[rt].l >= L && e[rt].r <= R) return e[rt].v % p;
110     pushdown(rt);
111     int mid = e[rt].l + e[rt].r >> 1;
112     if(L <= mid) uu += chaxun(rt * 2,L,R),uu %= p;
113     if(R > mid) uu += chaxun(rt * 2 + 1,L,R), uu %= p;
114     return uu % p;
115 }
116 
117 inline int treesum(int x,int y) {//查询 
118     long long ans = 0;
119     int tx = q[x].top;
120     int ty = q[y].top;
121     while(tx != ty) {
122         if(q[tx].d >= q[ty].d) {
123             ans += chaxun(1,q[tx].id,q[x].id);
124             ans %= p;
125             x = q[tx].f;tx = q[x].top;
126         }
127         else {
128             ans += chaxun(1,q[ty].id,q[y].id);
129             ans %= p;
130             y = q[ty].f;ty = q[y].top;
131         }
132     }
133     if(q[x].d > q[y].d)
134         ans += chaxun(1,q[y].id,q[x].id),ans %= p;
135     else
136         ans += chaxun(1,q[x].id,q[y].id),ans %= p;
137     return ans % p;
138 }
139 
140 int main() {
141     scanf("%d%d%d%d",&n,&m,&rr,&p);
142     for(int i = 1;i <= n; i++)
143         scanf("%d",&a[i]);
144     for(int i = 1;i < n; i++) {
145         int x,y;
146         scanf("%d%d",&x,&y);
147         add(x,y);
148         add(y,x);
149     }
150     dfs1(rr,0,1);
151     tot = 0;
152     dfs2(rr,rr);
153     build(1,1,n);
154     for(int i = 1;i <= m; i++) {
155         int x,y,z,ww;
156         scanf("%d",&ww);
157         if(ww == 1) {
158             scanf("%d%d%d",&x,&y,&z);
159             treeadd(x,y,z % p);
160         }
161         if(ww == 2) {
162             scanf("%d%d",&x,&y);
163             int aa = 0;
164             aa = treesum(x,y);
165             printf("%d
",aa % p);
166         }
167         if(ww == 3) {
168             scanf("%d%d",&x,&y);
169             pl(1,q[x].id,q[x].id + q[x].si - 1,y % p);
170         }
171         if(ww == 4) {
172             scanf("%d",&x);
173             printf("%d
",chaxun(1,q[x].id,q[x].id + q[x].si - 1) % p);
174         }
175     }
176     return 0;
177 }
原文地址:https://www.cnblogs.com/lipeiyi520/p/13488062.html