本来直接树剖就好了,但是树剖会多一个log非常不开心
我们来考虑维护dfs序,那么序列上的每个元素表示该点的答案
单点点权修改操作就是dfs序上段加操作
子树修改操作就是dfs序上段减一个数,然后每个点加上固定值乘以它的深度
具体的来讲。。。dfs序上每个点维护三个东西,叫v,tag和times,分别表示当前值,区间的加减,每个点的深度
单点修改就是v += d,而子树修改就是tag += d
于是用线段树维护就好了
1 /************************************************************** 2 Problem: 4034 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1128 ms 7 Memory:21796 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 12 using namespace std; 13 typedef long long ll; 14 const int N = 1e5 + 5; 15 const int Maxlen = N * 50; 16 17 inline int read(); 18 inline void print(ll); 19 20 struct edge { 21 int next, to; 22 edge(int _n = 0, int _t = 0) : next(_n), to(_t) {} 23 } e[N << 1]; 24 25 int first[N], tot; 26 27 struct seg { 28 seg *ls, *rs; 29 int times; 30 ll v, tag; 31 32 seg() { 33 ls = rs = NULL; 34 v = tag = times = 0; 35 } 36 37 #define Len (1 << 16) 38 inline void* operator new(size_t) { 39 static seg *mempool, *c; 40 if (c == mempool) 41 mempool = (c = new seg[Len]) + Len; 42 *c = seg(); 43 return c++; 44 } 45 #undef Len 46 47 inline void push() { 48 if (v) { 49 if (ls) ls -> v += v; 50 if (rs) rs -> v += v; 51 v = 0; 52 } 53 if (tag) { 54 if (ls) ls -> tag += tag; 55 if (rs) rs -> tag += tag; 56 tag = 0; 57 } 58 } 59 60 #define mid (l + r >> 1) 61 void build(int l, int r, ll *a, int *b) { 62 if (l == r) { 63 v = a[l], times = b[l]; 64 return; 65 } 66 ls = new()seg, rs = new()seg; 67 ls -> build(l, mid, a, b), rs -> build(mid + 1, r, a, b); 68 } 69 70 void modify(int l, int r, int L, int R, int d) { 71 if (L <= l && r <= R) { 72 v += d; 73 return; 74 } 75 push(); 76 if (L <= mid) ls -> modify(l, mid, L, R, d); 77 if (mid < R) rs -> modify(mid + 1, r, L, R, d); 78 } 79 80 void Modify(int l, int r, int L, int R, int dep, int d) { 81 if (L <= l && r <= R) { 82 v -= 1ll * d * (dep - 1), tag += d; 83 return; 84 } 85 push(); 86 if (L <= mid) ls -> Modify(l, mid, L, R, dep, d); 87 if (mid < R) rs -> Modify(mid + 1, r, L, R, dep, d); 88 } 89 90 ll query(int l, int r, int pos) { 91 if (l == r) return v + tag * times; 92 push(); 93 if (pos <= mid) return ls -> query(l, mid, pos); 94 return rs -> query(mid + 1, r, pos); 95 } 96 #undef mid 97 } *T; 98 99 struct tree_node { 100 int fa, v, dep; 101 int st, ed; 102 } tr[N]; 103 104 int n, m, cnt_seq; 105 ll a[N]; 106 int b[N]; 107 108 char buf[Maxlen], *c = buf; 109 int Len; 110 111 inline void Add_Edges(int x, int y) { 112 e[++tot] = edge(first[x], y), first[x] = tot; 113 e[++tot] = edge(first[y], x), first[y] = tot; 114 } 115 116 #define y e[x].to 117 void dfs(int p) { 118 int x; 119 a[tr[p].st = ++cnt_seq] = a[tr[tr[p].fa].st] + tr[p].v; 120 b[cnt_seq] = tr[p].dep; 121 for (x = first[p]; x; x = e[x].next) 122 if (y != tr[p].fa) { 123 tr[y].fa = p, tr[y].dep = tr[p].dep + 1; 124 dfs(y); 125 } 126 tr[p].ed = cnt_seq; 127 } 128 #undef y 129 130 int main() { 131 Len = fread(c, 1, Maxlen, stdin); 132 buf[Len] = ‘\0‘; 133 int i, oper, x; 134 n = read(), m = read(); 135 for (i = 1; i <= n; ++i) tr[i].v = read(); 136 for (i = 1; i < n; ++i) 137 Add_Edges(read(), read()); 138 dfs(1); 139 T = new()seg; 140 T -> build(1, n, a, b); 141 while (m--) { 142 oper = read(), x = read(); 143 if (oper == 1) T -> modify(1, n, tr[x].st, tr[x].ed, read()); 144 if (oper == 2) T -> Modify(1, n, tr[x].st, tr[x].ed, tr[x].dep, read()); 145 if (oper == 3) print(T -> query(1, n, tr[x].st)); 146 } 147 return 0; 148 } 149 150 inline int read() { 151 static int x, sgn; 152 x = 0, sgn = 1; 153 while (*c < ‘0‘ || ‘9‘ < *c) { 154 if (*c == ‘-‘) sgn = -1; 155 ++c; 156 } 157 while (‘0‘ <= *c && *c <= ‘9‘) 158 x = x * 10 + *c - ‘0‘, ++c; 159 return sgn * x; 160 } 161 162 inline void print(ll t) { 163 int tot = 0, pr[25]; 164 if (t < 0) putchar(‘-‘), t = -t; 165 tot = 0; 166 while (t) 167 pr[++tot] = t % 10, t /= 10; 168 if (!tot) putchar(‘0‘); 169 while (tot) putchar(pr[tot--] + ‘0‘); 170 putchar(‘\n‘); 171 }
时间: 2024-10-03 12:13:08