样例过了,0pts,调了数据发现挂在很灵异的地方。
挂点:给一个点增加了点权之后,和它完全没有子孙关系的点到根的权值和发生了变化,并且变化的差与增加的点权也毫无关系,甚至最大公因数 =1。
#include <iostream>
#include <vector>
using namespace std;
#define MAXN 100005
using ll = long long;
struct Tree
{
int u;
ll s, t;
} t[MAXN << 4];
vector<int> e[MAXN];
ll val[MAXN];
int st[MAXN], ed[MAXN];
int dfn[MAXN << 1];
int idx = 0;
void dfs(int p, int f)
{
st[p] = ++idx;
dfn[idx] = p;
for (int u : e[p])
{
if (u == f)
{
continue;
}
dfs(u, p);
}
ed[p] = ++idx;
dfn[idx] = -p;
}
int n, m;
void pushup(int p)
{
t[p] = {
t[p << 1].u + t[p << 1 | 1].u,
t[p << 1].s + t[p << 1 | 1].s,
0};
}
void pushdown(int p)
{
if (t[p].t)
{
t[p << 1].s += t[p << 1].u * t[p].t;
t[p << 1].t += t[p].t;
t[p << 1 | 1].s = t[p << 1 | 1].u * t[p].t;
t[p << 1 | 1].t += t[p].t;
t[p].t = 0;
}
}
void build(int p, int l, int r)
{
if (l == r)
{
if (dfn[l] > 0)
{
t[p] = {1, val[dfn[l]], 0};
}
else
{
t[p] = {-1, -val[-dfn[l]], 0};
}
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
pushup(p);
}
void add(int p, int l, int r, int q, ll v)
{
if (l == r)
{
t[p].s += t[p].u * v;
t[p].t += v;
return;
}
pushdown(p);
int mid = (l + r) >> 1;
if (mid >= q)
{
add(p << 1, l, mid, q, v);
}
else
{
add(p << 1 | 1, mid + 1, r, q, v);
}
pushup(p);
}
void add(int p, int l, int r, int ql, int qr, ll v)
{
if (ql <= l && r <= qr)
{
t[p].s += t[p].u * v;
t[p].t += v;
return;
}
pushdown(p);
int mid = (l + r) >> 1;
if (mid >= ql)
{
add(p << 1, l, mid, ql, qr, v);
}
if (mid < qr)
{
add(p << 1 | 1, mid + 1, r, ql, qr, v);
}
pushup(p);
}
ll query(int p, int l, int r, int q)
{
if (r <= q)
{
return t[p].s;
}
pushdown(p);
int mid = (l + r) >> 1;
if (mid < q)
{
return query(p << 1, l, mid, q) + query(p << 1 | 1, mid + 1, r, q);
}
else
{
return query(p << 1, l, mid, q);
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> val[i];
}
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1, 1);
build(1, 1, 2 * n);
while (m--)
{
int o, x;
ll a;
cin >> o >> x;
if (o == 1)
{
cin >> a;
add(1, 1, 2 * n, st[x], a);
add(1, 1, 2 * n, ed[x], a);
}
if (o == 2)
{
cin >> a;
add(1, 1, 2 * n, st[x], ed[x], a);
}
if (o == 3)
{
cout << query(1, 1, 2 * n, st[x]) << endl;
}
}
return 0;
}