CodeForces383C Propagating tree 思维 线段树 DFS序

CodeForces383C Propagating tree 思维 线段树 DFS序

题意

给定一颗1为根的树,由(1-n)编号,每个点具有点权,两种操作:

  1. 1 u val 表示给(u)号点增加权值val,同时还会影响子树,它的所有子节点-val,所有子节点的子节点-(-val)....

  2. 2 u 表示查询u的点权

[1 leq n,m leq 2 imes 10^5\ 1 leq a_i,val leq 1000\ ]

分析

我们发现每次只对单点或者一个子树操作,因此不必树链剖分,用DFS序即可维护。

如果只是单纯+val的话就是线段树模板了,但是此题会在下一层减,怎么办呢?既然不方便在加上做文章,不妨考虑在询问时处理。

规定:在奇数层操作时,全体加上val,否则减去val。在奇数层查询时,查维护的正值,否则取负号

这正是利用了相邻层总是一正一负的性质,让询问变得简单。

https://img2020.cnblogs.com/blog/1922757/202103/1922757-20210305201722236-1789756646.png

当然,实现用树状数组更好

代码

#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
",val[x] + seg.query(1,1,n,l[x],l[x]));
			}
			else printf("%d
",val[x] - seg.query(1,1,n,l[x],l[x]));
		}
	}
}

原文地址:https://www.cnblogs.com/hznumqf/p/14488238.html