Nowcoder 练习赛26E 树上路径 - 树剖
Description
给出一个n个点的树,1号节点为根节点,每个点有一个权值
你需要支持以下操作
1.将以u为根的子树内节点(包括u)的权值加val
2.将(u, v)路径上的节点权值加val
3.询问(u, v)路径上节点的权值两两相乘的和
Solution
维护 平方和与 数值和
修改 : 假如修改时有节点a, b, c, 增加t, 那么$sumsq = a^2 + b^2 + c^2 + 2*t*(a + b+c) + 3 * t^2$
所以对于所有的修改, $sumsq = sumsq + 2*t*sum + (r-l+1)*t^2$
这样平方和与数值和就可以维护了
查询只需要输出 $(sum * sum - sumsq) / 2$
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 #define rd read() 6 #define lson nd << 1 7 #define rson nd << 1 | 1 8 using namespace std; 9 10 const int N = 1e5 + 5; 11 const ll mod = 1e9 + 7; 12 13 int n, m; 14 int top[N], size[N], son[N], f[N], dep[N], cnt; 15 int head[N], tot; 16 int A[N], a[N], id[N]; 17 int Li[N << 2], Ri[N << 2]; 18 ll sum[N << 2], sum2[N << 2], inv, add[N << 2]; 19 20 struct edge{ 21 int nxt, to; 22 }e[N << 1]; 23 24 int read() { 25 int X = 0, p = 1; char c = getchar(); 26 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 27 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 28 return X * p; 29 } 30 31 void added(int u, int v) { 32 e[++tot].to = v; 33 e[tot].nxt = head[u]; 34 head[u] = tot; 35 } 36 37 void dfs1(int u) { 38 size[u] = 1; 39 for(int i = head[u]; i; i = e[i].nxt) { 40 int nt = e[i].to; 41 if(nt == f[u]) continue; 42 dep[nt] = dep[u] + 1; 43 f[nt] = u; 44 dfs1(nt); 45 size[u] += size[nt]; 46 if(size[nt] > size[son[u]]) son[u] = nt; 47 } 48 } 49 50 void dfs2(int u) { 51 id[u] = ++cnt; 52 A[cnt] = a[u]; 53 if(!son[u]) return; 54 top[son[u]] = top[u]; 55 dfs2(son[u]); 56 for(int i = head[u]; i; i = e[i].nxt) { 57 int nt = e[i].to; 58 if(nt == f[u] || nt == son[u]) continue; 59 top[nt] = nt; 60 dfs2(nt); 61 } 62 } 63 64 void pushdown(int nd) { 65 if(add[nd]) { 66 sum2[lson] += (2 * sum[lson] * add[nd] % mod + (Ri[lson] - Li[lson] + 1) * add[nd] % mod * add[nd] % mod) % mod; 67 sum2[lson] %= mod; 68 sum2[rson] += (2 * sum[rson] * add[nd] % mod + (Ri[rson] - Li[rson] + 1) * add[nd] % mod * add[nd] % mod) % mod; 69 sum2[rson] %= mod; 70 71 sum[lson] += (Ri[lson] - Li[lson] + 1) * add[nd] % mod; 72 sum[lson] %= mod; 73 sum[rson] += (Ri[rson] - Li[rson] + 1) * add[nd] % mod; 74 sum[rson] %= mod; 75 76 add[lson] += add[nd]; 77 add[rson] += add[nd]; 78 add[lson] %= mod; 79 add[rson] %= mod; 80 add[nd] = 0; 81 } 82 } 83 84 void update(int nd) { 85 sum[nd] = (sum[lson] + sum[rson]) % mod; 86 sum2[nd] = (sum2[lson] + sum2[rson]) % mod; 87 } 88 89 void build(int l, int r, int nd) { 90 if(l == r) { 91 Li[nd] = l; 92 Ri[nd] = r; 93 sum[nd] = A[l]; 94 sum2[nd] = A[l] * A[l] % mod; 95 return; 96 } 97 Li[nd] = l; 98 Ri[nd] = r; 99 int mid =(l + r) >> 1; 100 build(l, mid, lson); 101 build(mid + 1, r, rson); 102 update(nd); 103 } 104 105 void modify(int L, int R, int d, int l, int r, int nd) { 106 if(L <= l && r <= R) { 107 sum2[nd] += (2 * sum[nd] * d % mod + (r - l + 1) * d % mod * d % mod) % mod; 108 sum2[nd] %= mod; 109 sum[nd] += 1LL * d * (r - l + 1) % mod; 110 sum[nd] %= mod; 111 add[nd] += d; 112 add[nd] %= mod; 113 return; 114 } 115 pushdown(nd); 116 int mid = (l + r) >> 1; 117 if(mid >= L) modify(L, R, d, l, mid, lson); 118 if(mid < R) modify(L, R, d, mid + 1, r, rson); 119 update(nd); 120 } 121 122 ll query(int L, int R, int l, int r, int nd) { 123 if(L <= l && r <= R) return sum[nd]; 124 int mid = (l + r) >> 1; 125 ll re = 0; 126 pushdown(nd); 127 if(mid >= L) re = (re + query(L, R, l, mid, lson)) % mod; 128 if(mid < R) re = (re + query(L, R, mid + 1, r, rson)) % mod; 129 return re; 130 } 131 132 ll query2(int L, int R, int l, int r, int nd) { 133 if(L <= l && r <= R) return sum2[nd]; 134 int mid = (l + r) >> 1; 135 ll re = 0; 136 pushdown(nd); 137 if(mid >= L) re = (re + query2(L, R, l, mid, lson)) % mod; 138 if(mid < R) re = (re + query2(L, R, mid + 1, r, rson)) % mod; 139 return re; 140 } 141 142 ll query_po(int x, int y) { 143 ll re = 0, tmp, sum = 0; 144 for(; top[x] != top[y];) { 145 if(dep[top[x]] < dep[top[y]]) swap(x, y); 146 tmp = query(id[top[x]], id[x], 1, n, 1); 147 sum = (sum + tmp % mod) % mod; 148 tmp = query2(id[top[x]], id[x], 1, n, 1); 149 re = (re - tmp) % mod; 150 x = f[top[x]]; 151 } 152 if(dep[x] < dep[y]) swap(x, y); 153 tmp = query(id[y], id[x], 1, n, 1); 154 sum = (sum + tmp) % mod; 155 tmp = query2(id[y], id[x], 1, n, 1); 156 re = (re - tmp) % mod; 157 re = (re + sum * sum % mod) % mod; 158 re = (re % mod + mod) % mod; 159 re = re * inv % mod; 160 return re; 161 } 162 163 void modify_po(int x, int y, int d) { 164 for(; top[x] != top[y];) { 165 if(dep[top[x]] < dep[top[y]]) swap(x, y); 166 modify(id[top[x]], id[x], d, 1, n, 1); 167 x = f[top[x]]; 168 } 169 if(dep[x] < dep[y]) swap(x, y); 170 modify(id[y], id[x], d, 1, n, 1); 171 } 172 173 ll fc(ll ta, ll b) { 174 ll re = 0; 175 for(; b; b >>= 1, ta = (ta + ta) % mod) if( b & 1) re = (re + ta) % mod; 176 return re; 177 } 178 179 ll fpow(ll ta, ll b) { 180 ll re = 1; 181 for(; b; b >>= 1, ta = fc(ta, ta)) if(b & 1) re = fc(re, ta); 182 return re; 183 } 184 185 int main() 186 { 187 n = rd; m = rd; 188 for(int i = 1; i <= n; ++i) a[i] = rd; 189 for(int i = 1; i < n; ++i) { 190 int u = rd, v = rd; 191 added(u, v); added(v, u); 192 } 193 dfs1(1); 194 top[1] = 1; 195 dfs2(1); 196 build(1, n, 1); 197 inv = fpow(2, mod - 2); 198 for(int i = 1; i <= m; ++i) { 199 int k = rd; 200 if(k == 1) { 201 int u = rd, val = rd; 202 modify(id[u], id[u] + size[u] - 1, val, 1, n, 1); 203 } 204 if(k == 2) { 205 int u = rd, v = rd, val = rd; 206 modify_po(u, v, val); 207 } 208 if(k == 3) { 209 int u = rd, v = rd; 210 printf("%lld\n", query_po(u, v)); 211 } 212 } 213 }