改变一下标dfs序的顺序就可以变成裸题了。
这是老的dfs序但是这样子不方便修改。
我们标dfs序的时候隔层标,变成这样
隔层标的好处是对于题目而言的每一个修改操作,操作符相同的几个点的dfs序是连续的,这样我们就可以分两次改变两个连续区间,就是变成一道裸体了。举个例子比如我改变1的值,那么[2,3]区间是+val, [4,5]区间是-val,这就可以完成题目的要求。
关于如何这个连续区间是多少,从哪里开始,你在写个简单dp维护一下就可以了
int N,M;
ll c[max_];
il int lowbit(int x) { return x & (-x); }
il void change(int x, ll v) {
while (x <= N) {
c[x] += v;
x += lowbit(x);
}
}
il ll ask(int x) {
int ans = 0;
while (x){
ans += c[x];
x -= lowbit(x);
}return ans;
}
int dfn[max_], tt;
vector<int> xian[max_];
void dfs(int now, int fa,int dep,int op) {
if (dep % 2 == op % 2)dfn[now] = ++tt;
for (auto to : xian[now]) {
if (to == fa)continue;
dfs(to, now, dep + 1, op);
}
}
struct {
int start, siz;
}f[max_][3];
void dfs2(int now, int fa) {
f[now][1].start = f[now][0].start = inf;
for (auto to : xian[now]) {
if (to == fa)continue;
dfs2(to, now);
f[now][0].start = min(f[now][0].start, dfn[to]);
f[now][0].siz += 1 + f[to][1].siz;
f[now][1].start = min(f[now][1].start, f[to][0].start);
f[now][1].siz += f[to][0].siz;
}
}
int node[max_];
il void ini() {
N = read(); M = read();
re int A,B,i,temp;
for (i = 1; i <= N; i++) {
node[i] = read();
}
for (i = 1; i < N; i++) {
A = read(); B = read();
xian[A].push_back(B);
xian[B].push_back(A);
}
dfs(1, 0, 0, 0); dfs(1, 0, 0, 1);
for (i = 1; i <= N; i++) {
change(dfn[i], node[i]);
change(dfn[i] + 1, -node[i]);
}
dfs2(1, 0);
int op,x,val;
while (M--){
op = read(); x = read();
if (op == 1) {
val = read();
change(dfn[x], val);
change(dfn[x] + 1, -val);
if (f[x][0].start >= 1 && f[x][0].start <= N) {
change(f[x][0].start, -val);
change(f[x][0].start + f[x][0].siz, val);
}
if (f[x][1].start >= 1 && f[x][1].start <= N) {
change(f[x][1].start, val);
change(f[x][1].start + f[x][1].siz, -val);
}
}
else {
printf("%lld\n", ask(dfn[x]));
}
}
}
signed main() {
ini();
return 0;
}