树链剖分
树链剖分是基于重孩子将树划分成若干条链,配上对应的数据结构(例如这里的线段树)就可以维护树中的链,甚至可以直接维护子树。
貌似还有更高级的$\text{LCT}$,要搭配$\text{Splay}$。正在学习中。
具体证明。。待更。。
源码如下。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define For(i, a, b, s) for (re int i = a; i <= b; s) 9 #define maxx(a, b) a = max(a, b) 10 #define minn(a, b) a = min(a, b) 11 #define LL long long 12 #define INF (1 << 30) 13 14 inline int read() { 15 int w = 0, f = 1; char c = getchar(); 16 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 17 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 18 return w * f; 19 } 20 21 const int maxn = 1e5 + 5; 22 23 int N, M, R, P; 24 25 struct Edge { 26 int u, v, pre; 27 } e[maxn << 1]; 28 int ec, G[maxn]; 29 void init() { ec = 0; memset(G, -1, sizeof(G)); } 30 void add(int u, int v) { e[ec++] = (Edge){u, v, G[u]}; G[u] = ec-1; } 31 #define iter(i, u) for (register int i = G[u]; i != -1; i = e[i].pre) 32 // 33 34 int a[maxn], val[maxn]; // a按照下文mark的顺序 35 struct SegT { 36 #define lson (o << 1) 37 #define rson (o << 1 | 1) 38 int sumv[maxn << 4], tag[maxn << 4]; 39 void pushup(int o) { sumv[o] = sumv[lson] + sumv[rson]; } 40 void pushdown(int o, int l, int r) { 41 if (!tag[o]) return; 42 tag[lson] += tag[o]; tag[rson] += tag[o]; 43 int mid = (l + r) >> 1; 44 sumv[lson] = (sumv[lson] + (LL)tag[o] * (mid - l + 1)) % P; sumv[rson] = (sumv[rson] + (LL)tag[o] * (r - mid)) % P; 45 tag[o] = 0; 46 } 47 void build(int o, int l, int r) { 48 if (l == r) { sumv[o] = a[l]; tag[o] = 0; return; } 49 int mid = (l + r) >> 1; 50 build(lson, l, mid); build(rson, mid+1, r); 51 pushup(o); 52 } 53 void modify(int o, int l, int r, int ql, int qr, int v) { 54 if (ql <= l && r <= qr) { sumv[o] = (sumv[o] + (LL)v * (r - l + 1)) % P; tag[o] = (tag[o] + v) % P; return; } 55 pushdown(o, l, r); 56 int mid = (l + r) >> 1; 57 if (ql <= mid) modify(lson, l, mid, ql, qr, v); 58 if (mid < qr) modify(rson, mid+1, r, ql, qr, v); 59 pushup(o); 60 } 61 int query(int o, int l, int r, int ql, int qr) { 62 if (ql <= l && r <= qr) return sumv[o]; 63 pushdown(o, l, r); 64 int mid = (l + r) >> 1; LL res = 0; 65 if (ql <= mid) res += query(lson, l, mid, ql, qr); 66 if (mid < qr) res += query(rson, mid+1, r, ql, qr); 67 return res % P; 68 } 69 } T; 70 71 // 72 int son[maxn], link[maxn], mark[maxn], par[maxn], dep[maxn], topf[maxn], st[maxn], en[maxn], cnt = 0; 73 // son表示结点i的子树大小(包括i),link表示重孩子,mark表示结点i在线段树的位置,par表示父亲结点,dep表示结点i的深度,topf表示i所在的树链的头,st,ed表示子数所在区间。 74 void dfs1(int u, int fa) { 75 son[u] = 1; link[u] = u; dep[u] = dep[fa]+1; par[u] = fa; 76 iter(i, u) 77 if (e[i].v != fa) { 78 dfs1(e[i].v, u); 79 if (son[e[i].v] >= son[link[u]]) link[u] = e[i].v; // 必须写前面!!否则会挂(因为如果有儿子结点就一定会更新,放后面就不行了) 80 son[u] += son[e[i].v]; 81 } 82 } 83 void dfs2(int u, int fa, int head) { 84 mark[u] = st[u] = ++cnt; topf[u] = head; a[cnt] = val[u]; 85 if (link[u] != u) dfs2(link[u], u, head); 86 iter(i, u) 87 if (e[i].v != fa && e[i].v != link[u]) 88 dfs2(e[i].v, u, e[i].v); 89 en[u] = cnt; 90 } 91 #define swap(i, j) i ^= j ^= i ^= j; 92 void modify_link(int x, int y, int v) { 93 while (topf[x] != topf[y]) { 94 if (dep[topf[x]] < dep[topf[y]]) swap(x, y); 95 T.modify(1, 1, N, mark[topf[x]], mark[x], v); 96 x = par[topf[x]]; 97 } 98 if (dep[x] > dep[y]) swap(x, y); 99 T.modify(1, 1, N, mark[x], mark[y], v); 100 } 101 int query_link(int x, int y) { 102 LL res = 0; 103 while (topf[x] != topf[y]) { 104 if (dep[topf[x]] < dep[topf[y]]) swap(x, y); 105 res += T.query(1, 1, N, mark[topf[x]], mark[x]); 106 x = par[topf[x]]; 107 } 108 if (dep[x] > dep[y]) swap(x, y); 109 return (res + T.query(1, 1, N, mark[x], mark[y])) % P; 110 } 111 void modify_tree(int x, int v) { T.modify(1, 1, N, st[x], en[x], v); } 112 int query_tree(int x) { return T.query(1, 1, N, st[x], en[x]); } 113 // ### 114 115 int opt, x, y, z; 116 117 int main() { 118 init(); 119 N = read(), M = read(), R = read(), P = read(); 120 rep(i, 1, N) val[i] = read(); 121 rep(i, 1, N-1) { 122 x = read(), y = read(); 123 add(x, y); add(y, x); 124 } 125 dfs1(R, R); dfs2(R, R, R); T.build(1, 1, N); 126 rep(i, 1, M) { 127 opt = read(); 128 if (opt == 1) { 129 x = read(), y = read(), z = read(); 130 modify_link(x, y, z); 131 } 132 else if (opt == 4) { 133 x = read(); 134 printf("%d\n", query_tree(x)); 135 } else { 136 x = read(), y = read(); 137 if (opt == 2) printf("%d\n", query_link(x, y)); 138 else modify_tree(x, y); 139 } 140 } 141 return 0; 142 }