您的位置:首页 > 编程语言 > C语言/C++

【codeforces 384E】Propagating tree 中文题意&题解&代码(c++)

2015-12-21 21:36 549 查看

E. Propagating tree

time limit per test2 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

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.

Input

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.

Output

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.

Sample test(s)

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

output

3

3

0

Note

The values of the nodes are [1, 2, 1, 1, 2] at the beginning.

Then value 3 is added to node 2. It propagates and value -3 is added to it’s sons, node 4 and node 5. Then it cannot propagate any more. So the values of the nodes are [1, 5, 1,  - 2,  - 1].

Then value 2 is added to node 1. It propagates and value -2 is added to it’s sons, node 2 and node 3. From node 2 it propagates again, adding value 2 to it’s sons, node 4 and node 5. Node 3 has no sons, so it cannot propagate from there. The values of the nodes are [3, 3,  - 1, 0, 1].

题意:

给定n个点,m个询问的无向树(1为根)

下面n个数表示每个点的权值

下面n-1行给出树

操作1:x点权值+v , x的子节点中 与x在树中的层数奇偶性相同的节点权值+v,奇偶性不同的节点权值-v。

操作2:询问x点权值

题解:

要给x以及x的子节点加上一个值,很明显可以用DFS序建线段树,在进行区间修改,但难点是如何给不同奇偶性的节点加上不同的值,我们可以建两棵不同的线段树,一棵存奇数层的点,另一棵存偶数层的点,(假如在奇数线段树中,那就将每一个节点所代表的区间中 的 奇数层的点数 统计,这样的话每次传递时给这个节点所加的值就为tree[id].shu*v,偶数的线段树类似),每次进行添加的操作时,给其中一棵(与x奇偶性相同的那一棵)加 v,给另一棵加 -v ,最后要查询某一个点时,在两棵线段树中都进行查找,将所得的值相加即可。

注:想过用一棵线段树来写,但感觉线段树节点间传递的时候很乱ORZ,所以一棵线段树的写法请各位大神自行尝试,最好分享可以分享代码(-。-)!!

代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
#define lson (id*2)
#define rson (id*2+1)
#define MAX_N 200005
using namespace std;
vector<int>lin[MAX_N];
struct edge{
int val;//节点的总权值
int lazy;//lazy标记
int shu;//存共有多少层数奇(偶)的点
}tree[2][MAX_N*8];
//tree[0][MAX_N*8]表示偶数层线段树
//tree[1][MAX_N*8]表示奇数层线段树
int dp[MAX_N],w[MAX_N],size[MAX_N];
//dp表示节点的深度,w表示节点在线段树中的位置,size表示某个节点共有多少子节点
int a[MAX_N],mp[MAX_N];
//a存树上节点的值,mp映射线段树中的某个位置代表实际树的某个点
int num=0;
void dfs(int x,int f,int d)
{
num++;
dp[x]=d;
w[x]=num;
mp[num]=x;
size[x]=1;
for (int i=0;i<lin[x].size();i++)
{
int v=lin[x][i];
if (v!=f)
{
dfs(v,x,d+1);
size[x]+=size[v];
}
}
return ;
//求出dfs序以及各种乱七八糟的东西
}
void push_up(int id,int o)
{
tree[o][id].val=tree[o][lson].val+tree[o][rson].val;
tree[o][id].shu=tree[o][lson].shu+tree[o][rson].shu;
return ;
}
void push_down(int id,int l,int r,int o)
{
int mid=(l+r)/2;
tree[o][lson].val+=tree[o][id].lazy*tree[o][lson].shu;
tree[o][rson].val+=tree[o][id].lazy*tree[o][rson].shu;
tree[o][lson].lazy+=tree[o][id].lazy;
tree[o][rson].lazy+=tree[o][id].lazy;
tree[o][id].lazy=0;
return ;
}
void build_tree(int id,int l,int r,int o)
{
tree[o][id].lazy=0;
if (l==r)
{
if (dp[mp[l]]%2==o)
{
tree[o][id].shu=1;
tree[o][id].val=a[mp[l]];
//相同奇偶性才往进存
}
return ;
}
int mid=(l+r)/2;
build_tree(lson,l,mid,o);
build_tree(rson,mid+1,r,o);
push_up(id,o);
return ;
}
void add(int id,int l,int r,int L,int R,int v,int o)
{
if (l>=L&&r<=R)
{
tree[o][id].val+=tree[o][id].shu*v;
tree[o][id].lazy+=v;
return ;
}
push_down(id,l,r,o);

int mid=(l+r)/2;

if (mid>=L)
add(lson,l,mid,L,R,v,o);
if (mid+1<=R)
add(rson,mid+1,r,L,R,v,o);

push_up(id,o);
return ;
}
int query(int id,int l,int r,int o,int x)
{
if (l==r&&r==x)
return tree[o][id].val;

push_down(id,l,r,o);

int mid=(l+r)/2;
if (mid>=x)
return query(lson,l,mid,o,x);
if (mid+1<=x)
return query(rson,mid+1,r,o,x);
}
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
lin[u].push_back(v);
lin[v].push_back(u);
}

dfs(1,1,1);
build_tree(1,1,n,1);
build_tree(1,1,n,0);
for (int i=1;i<=m;i++)
{
int q,aa,bb;
scanf("%d",&q);
if (q==2)
{
scanf("%d",&aa);
int ans=query(1,1,n,1,w[aa])+query(1,1,n,0,w[aa]);
printf("%d\n",ans);
}
else
{
scanf("%d%d",&aa,&bb);
add(1,1,n,w[aa],w[aa]+size[aa]-1,bb,dp[aa]%2);
add(1,1,n,w[aa],w[aa]+size[aa]-1,-bb,(dp[aa]+1)%2);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: