洛谷3384树链剖分模板

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <cctype>
  8 #include <climits>
  9 #include <iostream>
 10 #include <iomanip>
 11 #include <algorithm>
 12 #include <string>
 13 #include <sstream>
 14 #include <stack>
 15 #include <queue>
 16 #include <set>
 17 #include <map>
 18 #include <vector>
 19 #include <list>
 20 #include <fstream>
 21 #define ri readint()
 22 #define gc getchar()
 23 #define R(x) scanf("%d", &x)
 24 #define W(x) printf("%d\n", x)
 25 #define init(a, b) memset(a, b, sizeof(a))
 26 #define rep(i, a, b) for (int i = a; i <= b; i++)
 27 #define irep(i, a, b) for (int i = a; i >= b; i--)
 28 #define ls  p << 1
 29 #define rs    p << 1 | 1
 30 using namespace std;
 31 
 32 typedef double db;
 33 typedef long long ll;
 34 typedef unsigned long long ull;
 35 typedef pair<int, int> P;
 36 const int inf = 0x3f3f3f3f;
 37 const ll INF = 1e18;
 38 
 39 inline int readint() {
 40     int x = 0, s = 1, c = gc;
 41     while (c <= 32)    c = gc;
 42     if (c == '-')    s = -1, c = gc;
 43     for (; isdigit(c); c = gc)
 44         x = x * 10 + c - 48;
 45     return x * s;
 46 }
 47 
 48 const int maxn = 1e5 + 5;
 49 int n, m, root, mod, a[maxn];
 50 int deep[maxn], fa[maxn], size[maxn], son[maxn], top[maxn], id[maxn], rnk[maxn], cnt;
 51 
 52 struct Edge {
 53     int to, nxt;
 54 }e[maxn << 1];
 55 int tot, head[maxn];
 56 
 57 struct Seg {
 58     int l, r, sum, laz;
 59 }t[maxn << 2];
 60 
 61 inline void add(int u, int v) {
 62     e[++tot].to = v, e[tot].nxt = head[u], head[u] = tot; 
 63 }
 64 
 65 inline int len(int p) {
 66     return t[p].r - t[p].l + 1;
 67 }
 68 
 69 inline void push_up(int p) {
 70     t[p].sum = (t[ls].sum + t[rs].sum) % mod;
 71 }
 72 
 73 inline void push_down(int p) {
 74     if (t[p].laz) {
 75         t[ls].laz += t[p].laz;
 76         t[rs].laz += t[p].laz;
 77         t[ls].sum = (t[ls].sum + len(ls) * t[p].laz % mod) % mod;
 78         t[rs].sum = (t[rs].sum + len(rs) * t[p].laz % mod) % mod;
 79         t[p].laz = 0;
 80     }
 81 }
 82 
 83 void build(int l, int r, int p) {
 84     t[p].l = l, t[p].r = r;
 85     if (l == r) {
 86         t[p].laz = 0;
 87         t[p].sum = rnk[l];
 88         return;
 89     }
 90     int mid = (l + r) >> 1;
 91     build(l, mid, ls);
 92     build(mid + 1, r, rs);
 93     push_up(p);
 94 }
 95 
 96 void segupd(int l, int r, int p, int k) {
 97     if (l <= t[p].l && t[p].r <= r) {
 98         t[p].sum = (t[p].sum + len(p) * k % mod) % mod;
 99         t[p].laz += k;
100         return;
101     }
102     int mid = (t[p].l + t[p].r) >> 1;
103     push_down(p);
104     if (l <= mid)    segupd(l, r, ls, k);
105     if (mid < r)    segupd(l, r, rs, k);
106     push_up(p);
107 }
108 
109 int segask(int l, int r, int p) {
110     if (l <= t[p].l && t[p].r <= r)    return t[p].sum;
111     int mid = (t[p].l + t[p].r) >> 1;
112     int res = 0;
113     push_down(p);
114     if (l <= mid)    res = (res + segask(l, r, ls)) % mod;
115     if (mid < r)    res = (res + segask(l, r, rs)) % mod;
116     return res;
117 }
118 
119 void dfs1(int u, int f, int depth) {//得到重儿子及一些普通信息
120     deep[u] = depth;
121     fa[u] = f;
122     size[u] = 1;
123     for (int i = head[u]; i; i = e[i].nxt) {
124         int v = e[i].to;
125         if (v == f)    continue;
126         dfs1(v, u, depth + 1);
127         if (size[v] > size[son[u]])    son[u] = v;
128         size[u] += size[v];
129     }
130 }
131 
132 void dfs2(int u, int topf) {//将重链排列在一起以便线段树维护
133     id[u] = ++cnt;
134     rnk[cnt] = a[u];
135     top[u] = topf;
136     if (!son[u])    return;
137     dfs2(son[u], topf);
138     for (int i = head[u]; i; i = e[i].nxt) {
139         int v = e[i].to;
140         if (v != son[u] && v != fa[u])
141             dfs2(v, v);
142     }
143 }
144 
145 void Update(int x, int y, int z) {//类似倍增的方式
146     while (top[x] != top[y]) {
147         if (deep[top[x]] < deep[top[y]])    swap(x, y);
148         segupd(id[top[x]], id[x], 1, z);
149         x = fa[top[x]];
150     }
151     if (deep[x] > deep[y])    swap(x, y);
152     segupd(id[x], id[y], 1, z);
153 }
154 
155 int Query(int x, int y) {
156     int ans = 0;
157     while (top[x] != top[y]) {
158         if (deep[top[x]] < deep[top[y]])    swap(x, y);
159         ans = (ans + segask(id[top[x]], id[x], 1)) % mod;
160         x = fa[top[x]];
161     }
162     if (deep[x] > deep[y])    swap(x, y);
163     ans = (ans + segask(id[x], id[y], 1)) % mod;
164     return ans;
165 }
166 
167 int main() {
168     n = ri, m = ri, root = ri, mod = ri;
169     rep(i, 1, n) {
170         a[i] = ri;
171         a[i] %= mod;
172     }
173     rep(i, 1, n - 1) {
174         int x = ri, y = ri;
175         add(x, y);
176         add(y, x);
177     }
178     dfs1(root, 0, 1);
179     dfs2(root, root);
180     build(1, n, 1);
181     
182     while (m--) {
183         int op = ri, x, y, z;
184         if (op == 1) {
185             x = ri, y = ri, z = ri;
186             Update(x, y, z % mod);//从x到y的最短路径上的节点都加z
187         } else if (op == 2) {
188             x = ri, y = ri;
189             W(Query(x, y));//查询x到y的最短路节点和
190         } else if (op == 3) {
191             x = ri, z = ri;
192             segupd(id[x], id[x] + size[x] - 1, 1, z % mod);//对x的子树全加z
193         } else {
194             x = ri;
195             W(segask(id[x], id[x] + size[x] - 1, 1));//查询x的子树节点和
196         }
197     }
198     return 0;
199 }

猜你喜欢

转载自www.cnblogs.com/AlphaWA/p/10439238.html