传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4765
【题解】
我们可以分块来做。
首先我们预处理每块的答案,并且处理出来f[x,i]表示x改动了,i块有多少个要改动。
修改用DFS序+BIT来块中暴力,整块用上面的方法处理即可。
询问块中BIT暴力,整块直接查答案即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10, BLOCK = 310, N = 1e5 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, d[M], rt; int head[M], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } namespace BIT { const int M = 4e5 + 10; ull c[M]; int n; # define lb(x) (x&(-x)) inline void set(int _n) { n = _n; memset(c, 0, sizeof c); } inline void edt(int x, int d) { for (; x<=n; x+=lb(x)) c[x] += d; } inline ull ask(int x) { ull ret = 0; for (; x; x-=lb(x)) ret += c[x]; return ret; } # undef lb } ull bans[M]; int bl[M]; int f[N][BLOCK + 100], sz; int in[M], out[M], DFN=0, t[BLOCK + 100]; inline void dfs(int x, int fa) { t[bl[x]] ++; for (int i=1; i<=sz; ++i) f[x][i] = t[i]; in[x] = ++DFN; for (int i=head[x]; i; i=nxt[i]) { if(to[i] == fa) continue; dfs(to[i], x); } out[x] = DFN; t[bl[x]] --; } int main() { int q; scanf("%d%d", &n, &q); BIT::set(n); for (int i=1; i<=n; ++i) scanf("%d", d+i); for (int i=1, u, v; i<=n; ++i) { scanf("%d%d", &u, &v); if(u == 0) rt = v; else adde(u, v); bl[i] = (i-1)/BLOCK+1; } sz = bl[n]; dfs(rt, 0); for (int i=1; i<=n; ++i) BIT::edt(in[i], d[i]); for (int i=1; i<=n; ++i) bans[bl[i]] += BIT::ask(out[i]) - BIT::ask(in[i]-1); int op, x, y; while(q--) { scanf("%d%d%d", &op, &x, &y); if(op == 1) { BIT::edt(in[x], y-d[x]); for (int i=1; i<=sz; ++i) bans[i] += (ull)f[x][i]*(y-d[x]); d[x] = y; } else { ull ans = 0; if(bl[x] == bl[y]) { for (int i=x; i<=y; ++i) ans += BIT::ask(out[i]) - BIT::ask(in[i]-1); printf("%llu\n", ans); continue; } for (int i=bl[x]+1; i<=bl[y]-1; ++i) ans += bans[i]; for (int i=x; i<=n && bl[i]==bl[x]; ++i) ans += BIT::ask(out[i]) - BIT::ask(in[i]-1); for (int i=y; i && bl[i]==bl[y]; --i) ans += BIT::ask(out[i]) - BIT::ask(in[i]-1); printf("%llu\n", ans); } } return 0; }