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

Codeforces 383C Propagating tree 题解&代码

2015-12-15 17:12 302 查看
题意:

给出一个以1为根节点的n个节点的树,有两个操作:

1、操作为1 x val,给x节点增加val

2、操作为2 x,查询x节点当前的值

每次给一个节点的值增加val,这个节点的孩子的值将会增加-val

如此,给一个节点增加val就相当于它的子节点增加-val,它的子节点的子节点增加val…如此直到叶子节点

思路:

每次都是给修改节点子树中与修改节点深度奇偶性相同的节点增加val,给与修改节点深度奇偶性不同的节点增加-val

我们可以建两个范围均为[1,n]的线段树,线段树的根节点编号为0和1,表示他们存储了深度(深度大小在一遍dfs中很容易O(n)地记录下来)分别为奇数和偶数的节点的状态。如果某个线段树存储了深度为奇数的节点状态,那么如果这个线段树在建树时遇到了深度为偶数的节点,就作一个不可能标记(不可能由数据范围得到的值),否则插入现在应当插入线段树的点。反之则反。

插入操作是同时对两个树进行的,在与待插入节点x奇偶性相同的树中,给x和它的子树中所有节点都增加val;在与待插入节点x奇偶性相反的树中,给x和它的子树中所有节点都增加-val。由于两个树中的存储情况正好互补(即如果一个点在线段树0中无法查询,那它一定可以在线段树1中被查找到),所以其子树中每一个存在的节点都唯一地被改变了val值(存在不可能标记的时候对这个节点不做修改)。区间修改和编号重排用普通的dfs序+lazy[]标记即可。

单点查询操作也是两个树同时进行,由于两个树的互补性,一定有一个树可以得到正确答案,另一个树中则无法查询该节点(节点上有不可能标记),查询到结果的树返回结果,无法查询的树只要返回0(不改变结果)即可,加起来一定是正确答案。

#include<iostream>
#include<vector>
#include<stdio.h>
#define lson (o<<1)
#define rson ((o<<1)|1)
#define INF 2100000000
using namespace std;
const int maxn=200005;
vector<int> edge[maxn];
int n,m,c,x,y,cnt,val[maxn],value[2][maxn],tot[2],v[2][maxn],deep[maxn],in[maxn],out[maxn],lazy[2][maxn*4];
void dfs(int x,int pre)
{
deep[x]=deep[pre]+1;
in[x]=++cnt;
v[deep[x]%2][in[x]]=x;
for(int i=0;i<edge[x].size();i++)
if(edge[x][i]!=pre)dfs(edge[x][i],x);
out[x]=cnt;
}
void build(int z,int o,int l,int r)
{
if(l==r)
{
if(v[z][l])value[z][l]=val[v[z][l]];
else value[z][l]=INF;
return;
}
int mid=(l+r)/2;
build(z,lson,l,mid);
build(z,rson,mid+1,r);
}
void pushdown(int z,int o,int l,int r)
{
if(!lazy[z][o])return;
if(l==r)
{
if(value[z][l]!=INF)
value[z][l]+=lazy[z][o];
}
else
{
lazy[z][lson]+=lazy[z][o];
lazy[z][rson]+=lazy[z][o];
}
lazy[z][o]=0;
}
void addtree(int z,int o,int l,int r,int L,int R,int c)
{
pushdown(z,o,l,r);
if(l>R || r<L)return;
if(l>=L && r<=R)
{
lazy[z][o]+=c;
return;
}
int mid=(l+r)/2;
addtree(z,lson,l,mid,L,R,c);
addtree(z,rson,mid+1,r,L,R,c);
}
int query(int z,int o,int l,int r,int L,int R)
{
pushdown(z,o,l,r);
if(l>R || r<L)return 0;
if(l==r)
{
if(value[z][l]==INF)return 0;
return value[z][l];
}
int mid=(l+r)/2;
return query(z,lson,l,mid,L,R)+query(z,rson,mid+1,r,L,R);
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
edge[x].push_back(y);
edge[y].push_back(x);
}
dfs(1,0);
build(0,1,1,n);
build(1,1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&c);
if(c==1)
{
scanf("%d%d",&x,&y);
addtree(deep[x]%2,1,1,n,in[x],out[x],y);
addtree(!(deep[x]%2),1,1,n,in[x],out[x],-y);
}
else
{
scanf("%d",&x);
printf("%d\n",query(deep[x]%2,1,1,n,in[x],in[x])+query(!(deep[x]%2),1,1,n,in[x],in[x]));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: