实在是找不到问题了, 就简单的一个树剖板子, 做一个guo一个。
#include <iostream>
#include <cstdio>
//#define int long long
using namespace std;
const int N = 4e5;
int n, m;
int a[N];
int re() {
int x = 0, f = 1;
char ch = getchar();
while(ch < '0'||ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while (ch <= '9'&&ch >= '0') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int cnt;
int head[N<<2];
struct bal {
int nxt;
int to;
};
bal e[N<<1];
void add(int u, int v) {
++cnt;
e[cnt].nxt = head[u];
e[cnt].to = v;
head[u] = cnt;
}
int fa[N];
int tot[N];
int son[N];
int dep[N];
void dfs1(int x, int f, int deep) {
dep[x] = deep;
tot[x] = 1;
fa[x] = f;
for(int i = head[x]; i; i = e[i].nxt) {
int v = e[i].to;
if(v == f) continue;
dfs1(v, x, deep + 1);
if(tot[v] > tot[son[x]])
son[x] = v;
tot[x] += tot[v];
}
}
int num;
int b[N];
int top[N];
int idx[N];
void dfs2(int x, int ftop) {
top[x] = ftop;
idx[x] = ++num;
b[num] = a[x];
if(son[x]) dfs2(son[x], ftop);
for(int i = head[x]; i; i = e[i].nxt) {
int v = e[i].to;
if(v == fa[x]||v == son[x])
continue;
dfs2(v, v);
}
}
struct ball {
int l, r;
int sum;
int size;
int lazy;
};
ball t[N<<2];
void update(int k) {
t[k].sum = t[k<<1].sum + t[k<<1|1].sum;
}
void build(int p, int l, int r) {
if(l <= 0||r > n||l > r) return ;
t[p].l = l; t[p].r = r;
t[p].size = r - l + 1;
if(l == r) {
t[p].sum = b[l];
return ;
}
int mid = (l + r) >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid + 1, r);
update(p);
}
void Point_sum(int p, int l, int r, int val) {
if(r == t[p].r&&t[p].l == l) {
t[p].sum += val;
return ;
}
int mid = (t[p].l + t[p].r) >> 1;
if(mid >= l) Point_sum(p<<1, l, r, val);
if(mid < r) Point_sum(p<<1|1, l, r, val);
update(p);
}
void pushdown(int p) {
if(!t[p].lazy) return ;
t[p<<1].sum += t[p<<1].size * t[p].lazy;
t[p<<1|1].sum += t[p<<1|1].size * t[p].lazy;
t[p<<1].lazy += t[p].lazy;
t[p<<1|1].lazy += t[p].lazy;
t[p].lazy = 0;
}
void Tree_addition(int p, int l, int r, int val) {
if(l > r||l < 0||r > n) return ;
if(t[p].l >= l&&t[p].r <= r) {
t[p].sum += (t[p].size * val);
t[p].lazy += val;
return ;
}
int mid = (t[p].l + t[p].r)>>1;
pushdown(p);
if(mid >= l) Tree_addition(p<<1, l, r, val);
if(mid < r) Tree_addition(p<<1|1, l, r, val);
update(p);
return ;
}
int Tree_sum(int p, int l, int r) {
int ans = 0;
if(t[p].l >= l&&t[p].r <= r) {
ans += t[p].sum;
return ans;
}
pushdown(p);
int mid = (t[p].l + t[p].r) >> 1;
if(mid >= l) ans += Tree_sum(p<<1, l, r);
if(mid < r) ans += Tree_sum(p<<1|1, l, r);
return ans;
}
void Interval_sum(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]])
swap(x, y);
ans += Tree_sum(1, idx[top[x]], idx[x]);
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x, y);
ans += Tree_sum(1, idx[y], idx[x]);
printf("%d\n", ans);
}
signed main() {
// freopen("P3178_1.in", "r", stdin);
// freopen("dsd.out", "w", stdout);
int u, v, op;
n = re(); m = re();
for(int i = 1; i <= n; i++)
a[i] = re();
for(int i = 1; i < n; i++) {
scanf("%d%d", &u,&v);
add(u, v); add(v, u);
}
dfs1(1, 0, 1);
dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i <= m; i++) {
op = re(); u = re();
if(op == 1) {
v = re();
Point_sum(1, idx[u], idx[u], v);
}
if(op == 2) {
v = re();
Tree_addition(1, idx[u], idx[u] + tot[u] - 1, v);
}
if(op == 3)
Interval_sum(1, u);
}
return 0;
}