原题链接
Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numbered from 1 to n, each node i having an initial value ai. The root of the tree is node 1.
This tree has a special property: when a value val is added to a value of node i, the value -val is added to values of all the children of node i. Note that when you add value -val to a child of node i, you also add -(-val) to all children of the child of node i and so on. Look an example explanation to understand better how it works.
This tree supports two types of queries:
- "1 x val" — val is added to the value of node x;
- "2 x" — print the current value of node x.
In order to help Iahub understand the tree better, you must answer m queries of the preceding type.
The first line contains two integers n and m (1 ≤ n, m ≤ 200000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1000). Each of the next n–1 lines contains two integers vi and ui (1 ≤ vi, ui ≤ n), meaning that there is an edge between nodes vi and ui.
Each of the next m lines contains a query in the format described above. It is guaranteed that the following constraints hold for all queries: 1 ≤ x ≤ n, 1 ≤ val ≤ 1000.
For each query of type two (print the value of node x) you must print the answer to the query on a separate line. The queries must be answered in the order given in the input.
5 5 1 2 1 1 2 1 2 1 3 2 4 2 5 1 2 3 1 1 2 2 1 2 2 2 4
3 3 0
#include <bits/stdc++.h>
#define MOD 1000000007
#define maxn 200005
#define INF 1e18
using namespace std;
typedef long long ll;
struct Node{
int l1, r1, l2, r2;
int s1, s2, h;
}node[maxn];
int num[maxn<<2], add[maxn<<2], vis[maxn], value[maxn], p[maxn];
vector<int> v[maxn];
int e1, e2, odd, even;
void dfs1(int j, int f, int h){
if(h&1)
odd++;
else
even++;
for(int i = 0; i < v[j].size(); i++){
int k = v[j][i];
if(k != f)
dfs1(k, j, h+1);
}
}
void dfs2(int j, int f, int h){
if(h&1){
vis[++e1] = j;
p[j] = e1;
node[j].s1 = 1;
}
else{
vis[++e2] = j;
p[j] = e2;
node[j].s2 = 1;
}
node[j].h = h;
node[j].l1 = e1;
node[j].l2 = e2;
for(int i = 0; i < v[j].size(); i++){
int k = v[j][i];
if(k != f)
dfs2(k, j, h+1);
}
if(node[j].s1)
node[j].r1 = e1;
else{
if(e1 > node[j].l1){
node[j].s1 = 1;
node[j].r1 = e1;
node[j].l1++;
}
}
if(node[j].s2)
node[j].r2 = e2;
else{
if(e2 > node[j].l2){
node[j].s2 = 1;
node[j].r2 = e2;
node[j].l2++;
}
}
}
void Build(int s, int l, int r){
if(l == r){
num[s] = value[vis[l]];
return ;
}
int mid = (l + r) >> 1;
Build(s<<1, l, mid);
Build(s<<1|1, mid+1, r);
num[s] = num[s<<1] + num[s<<1|1];
}
void pushdown(int s, int L, int R){
int mid = (L + R) >> 1;
num[s<<1] += add[s] * (mid - L + 1);
num[s<<1|1] += add[s] * (R - mid);
add[s<<1] += add[s];
add[s<<1|1] += add[s];
add[s] = 0;
}
void Update(int s, int l, int r, int L, int R, int h){
if(l == L && R == r){
add[s] += h;
num[s] += (r - l + 1) * h;
return ;
}
if(add[s])
pushdown(s, L, R);
int mid = (L + R) >> 1;
if(r <= mid)
Update(s<<1, l, r, L, mid, h);
else if(l > mid)
Update(s<<1|1, l, r, mid+1, R, h);
else{
Update(s<<1, l, mid, L, mid, h);
Update(s<<1|1, mid+1, r, mid+1, R, h);
}
num[s] = num[s<<1] + num[s<<1|1];
}
int Query(int s, int L, int R, int e){
if(L == R){
return num[s];
}
if(add[s])
pushdown(s, L, R);
int mid = (L + R) >> 1;
if(e <= mid)
return Query(s<<1, L, mid, e);
return Query(s<<1|1, mid+1, R, e);
}
int main(){
// freopen("in.txt", "r", stdin);
int n, m, a, b, c;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d", value+i);
for(int i = 1; i < n; i++){
scanf("%d%d", &a, &b);
v[a].push_back(b);
v[b].push_back(a);
}
dfs1(1, -1, 1);
e1 = 0;
e2 = odd;
dfs2(1, -1, 1);
Build(1, 1, n);
while(m--){
scanf("%d", &a);
if(a == 1){
scanf("%d%d", &b, &c);
if(node[b].s1){
if(node[b].h % 2 == 0)
c = -c;
Update(1, node[b].l1, node[b].r1, 1, n, c);
}
c = abs(c);
if(node[b].s2){
if(node[b].h&1)
c = -c;
Update(1, node[b].l2, node[b].r2, 1, n, c);
}
}
else{
scanf("%d", &b);
printf("%d\n", Query(1, 1, n, p[b]));
}
}
return 0;
}