CodeForces383C Propagating tree 思维 线段树 DFS序
CodeForces383C Propagating tree 思维 线段树 DFS序
题意
给定一颗1为根的树,由\(1-n\)编号,每个点具有点权,两种操作:
-
1 u val 表示给\(u\)号点增加权值val,同时还会影响子树,它的所有子节点-val,所有子节点的子节点-(-val)....
-
2 u 表示查询u的点权
\[1 \leq n,m \leq 2\times 10^5\\
1 \leq a_i,val \leq 1000\\
\]
分析
我们发现每次只对单点或者一个子树操作,因此不必树链剖分,用DFS序即可维护。
如果只是单纯+val的话就是线段树模板了,但是此题会在下一层减,怎么办呢?既然不方便在加上做文章,不妨考虑在询问时处理。
规定:在奇数层操作时,全体加上val,否则减去val。在奇数层查询时,查维护的正值,否则取负号
这正是利用了相邻层总是一正一负的性质,让询问变得简单。
当然,实现用树状数组更好
代码
#include<bits/stdc++.h>
#define eps 1e-8
#define equals(a,b) (fabs(a - b) < eps)
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
ll rd(){
ll x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == -1) f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
struct SegmentTree{
int n;
vector<int> sum,tag;
SegmentTree(){}
SegmentTree(int n):n(n),sum(((n + 1) << 2)),tag(((n + 1) << 2)) {}
int push_up(int i){
sum[i] = sum[i << 1] + sum[i << 1|1];
}
void update(int i,int l,int r,int v){
sum[i] += (r - l + 1) * v;
tag[i] += v;
}
void push(int i,int l,int r){
int mid = l + r >> 1;
if(tag[i]) {
update(i << 1,l,mid,tag[i]);
update(i << 1|1,mid + 1,r,tag[i]);
tag[i] = 0;
}
}
void update(int i,int l,int r,int L,int R,int v){
if(l > R || r < L) return;
if(l >= L && r <= R) return update(i,l,r,v);
int mid = l + r >> 1;
push(i,l,r);
update(i << 1,l,mid,L,R,v);
update(i << 1|1,mid + 1,r,L,R,v);
push_up(i);
}
int query(int i,int l,int r,int L,int R){
if(l > R || r < L) return 0;
if(l >= L && r <= R) return sum[i];
int mid = l + r >> 1;
push(i,l,r);
return query(i << 1,l,mid,L,R) + query(i << 1|1,mid + 1,r,L,R);
}
};
vector<int> e[200005];
int l[200005];
int r[200005];
int dep[200005];
int tt;
void dfs(int u,int fa){
l[u] = ++tt;
for(auto it:e[u]) {
if(it == fa) continue;
dep[it] = dep[u] + 1;
dfs(it,u);
}
r[u] = tt;
}
int main(){
int n = rd();
SegmentTree seg(n);
vector<int> val(n + 1);
int m = rd();
for(int i = 1;i <= n;i++){
val[i] = rd();
}
for(int i = 1;i < n;i++){
int u = rd();
int v = rd();
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
while(m--){
int op = rd();
if(op == 1) {
int x = rd();
int y = rd();
if(dep[x] & 1) {
seg.update(1,1,n,l[x],r[x],y);
}
else seg.update(1,1,n,l[x],r[x],-y);
}
else{
int x = rd();
if(dep[x] & 1) {
printf("%d\n",val[x] + seg.query(1,1,n,l[x],l[x]));
}
else printf("%d\n",val[x] - seg.query(1,1,n,l[x],l[x]));
}
}
}