CF383C Propagating tree【线段树】

题意:一棵树,两个操作:1.给一个节点加val,下面一层的节点减val,再下面一层加val,以此类推 2.查询某节点的值


思路:dfs序处理,把节点分为奇数层与偶数层。线段树上两个标记,一个是奇数层的、一个偶数层的。这样奇数层的标记传到最底层,如果最底层是奇数层的,那么加上这个值;反之减去。


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define lson(x) 2*x
#define rson(x) 2*x+1
typedef long long ll;
typedef pair pii;
const int maxn = 200005;
int in[maxn],out[maxn],point[maxn];
struct Edge
{
	int to,next;
}edge[2*maxn];
int head[maxn],tot,t,vis[maxn];
int a[maxn],num[maxn];
int chen[maxn];

struct data
{
	int l,r,p;
	int laz0,laz1,num;
}node[maxn*4];

void init()
{
	memset(head,-1,sizeof head);
	memset(vis,0,sizeof vis);
	tot = 0;
	t = 0;
}

void add(int x,int y)
{
	edge[tot].to = y;
	edge[tot].next = head[x];
	head[x] = tot++;
}

void dfs(int x,int k)
{
	vis[x] = 1;
	in[x] = ++t;
	num[t] = a[x];
	point[t] = x; 
	chen[x] = k;
	for(int i = head[x]; i != -1; i = edge[i].next)
	{
		int y = edge[i].to;
		if(vis[y]) continue;
		dfs(y,k^1);
	}
	out[x] = t;	
}

void down(int cnt)
{
	if(node[cnt].laz0 == 0 && node[cnt].laz1 == 0) return;
	int tg0 = node[cnt].laz0;
	int tg1 = node[cnt].laz1;
	node[lson(cnt)].laz0 += tg0;
	node[lson(cnt)].laz1 += tg1;
	node[rson(cnt)].laz0 += tg0;
	node[rson(cnt)].laz1 += tg1;
	if(node[lson(cnt)].p)
	{
		if(chen[node[lson(cnt)].p] == 0)
			node[lson(cnt)].num += tg0 - tg1;
		else
			node[lson(cnt)].num += tg1 - tg0;
	}
	if(node[rson(cnt)].p)
	{
		if(chen[node[rson(cnt)].p] == 0)
			node[rson(cnt)].num += tg0 - tg1;
		else
			node[rson(cnt)].num += tg1 - tg0;
	}

	node[cnt].laz0 = 0;
	node[cnt].laz1 = 0;
}

void build(int x,int y, int cnt)
{
	node[cnt].l = x;
	node[cnt].r = y;
	node[cnt].laz0 = 0;
	node[cnt].laz1 = 0;
	node[cnt].p = 0;
	if(x == y)
	{
		node[cnt].p = point[x];
		node[cnt].num = num[x];
		return;
	}
	int mid = (x+y) / 2;
	build(x,mid,lson(cnt));
	build(mid+1,y,rson(cnt));
}

void up(int x,int y,int cnt,int val,int k)
{
	if(x == node[cnt].l && y == node[cnt].r)
	{
		if(k == 0)
		{
			node[cnt].laz0 += val;
			if(node[cnt].p)
			{
				if(chen[node[cnt].p] == 0)
					node[cnt].num += val;
				else
					node[cnt].num -= val;
			}	
		}
		else
		{
			node[cnt].laz1 += val;
			if(node[cnt].p)
			{
				if(chen[node[cnt].p] == 1)
					node[cnt].num += val;
				else
					node[cnt].num -= val;
			}
		}
		return;
	}
	down(cnt);
	int mid = (node[cnt].l + node[cnt].r) / 2;
	if(y <= mid)
		up(x,y,lson(cnt),val,k);
	else if(x >= mid+1)
		up(x,y,rson(cnt),val,k);
	else
	{
		up(x,mid,lson(cnt),val,k);
		up(mid+1,y,rson(cnt),val,k);
	}
}

int fid(int x,int y,int cnt)
{	
	if(x == node[cnt].l && y == node[cnt].r)
	{
		return node[cnt].num;
	}
	down(cnt);
	int mid = (node[cnt].l + node[cnt].r) / 2;
	if(y <= mid)
		return fid(x,y,lson(cnt));
	else if(x >= mid+1)
		return fid(x,y,rson(cnt));
}

int main(void)
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		init();
		for(int i = 1; i <= n; i++)
			scanf("%d",&a[i]);
		for(int i = 1; i < n; i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			add(x,y);
			add(y,x);
		}
		dfs(1,0);
		build(1,n,1);
		while(m--)
		{
			int op,x,val;
			scanf("%d%d",&op,&x);
			if(op == 1)
			{
				scanf("%d",&val);
				up(in[x],out[x],1,val,chen[x]);
			}
			else
				printf("%d\n",fid(in[x],in[x],1));
		}
	}
	return 0;
}


你可能感兴趣的:(线段树)