Description
给定一棵有根树,每次操作一个结点(将它加上 (v),孩子减去 (v),孩子的孩子加上 (v),以此类推),或者查询一个结点的值。
Solution
考虑维护两个序列,一个序列中所有深度为奇数的点是有效的,另一个序列中所有深度为偶数的点是有效的。如果操作的一个点是奇数深度的,那么就在前者中加,后者中减,若是偶数深度则恰好相反。当我们取出一个点的权值的时候,根据它是奇数深度的点还是偶数深度的点到对应的序列中取即可。
通过 DFS 序转化为区间操作单点询问,再通过差分转化为单点修改区间询问,于是用树状数组处理即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
struct BIT
{
vector<int> a;
int size;
BIT(int size) : size(size)
{
a.resize(size + 2);
}
int lowbit(int i)
{
return i & (-i);
}
void add(int i, int v)
{
while (i <= size)
{
a[i] += v;
i += lowbit(i);
}
}
int sum(int i)
{
int ans = 0;
while (i > 0)
{
ans += a[i];
i -= lowbit(i);
}
return ans;
}
void Modify(int l, int r, int v)
{
add(l, v);
add(r + 1, -v);
}
int Query(int r)
{
return sum(r);
}
};
vector<int> g[N];
int dep[N], vis[N], dfn[N], fin[N], ind;
void dfs(int p)
{
dfn[p] = ++ind;
vis[p] = 1;
for (int q : g[p])
{
if (vis[q] == 0)
{
dep[q] = dep[p] + 1;
dfs(q);
}
}
fin[p] = ind;
}
signed main()
{
int n, m;
cin >> n >> m;
BIT *bit[2];
bit[0] = new BIT(n);
bit[1] = new BIT(n);
vector<int> a(n + 2);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1);
for (int i = 1; i <= n; i++)
{
bit[0]->Modify(dfn[i], dfn[i], a[i]);
bit[1]->Modify(dfn[i], dfn[i], a[i]);
}
for (int i = 1; i <= m; i++)
{
int t1, t2, t3;
cin >> t1 >> t2;
if (t1 == 1)
{
cin >> t3;
bit[dep[t2] & 1]->Modify(dfn[t2], fin[t2], t3);
bit[(dep[t2] & 1) ^ 1]->Modify(dfn[t2], fin[t2], -t3);
}
else
{
cout << bit[dep[t2] & 1]->Query(dfn[t2]) << endl;
}
}
}