CodeForces 384E Propagating tree (dfs序)
2016-05-24 09:32
465 查看
题目传送门:http://codeforces.com/problemset/problem/384/E
题意:给你一棵树,根节点1,每个节点有权值,然后你可以对一个节点进行操作,在它的权值上加上val,但是它的子节点需要加上−val,它的子节点的子节点就要加上−(−val),就是子节点加得的值和父节点相反,询问你某个节点当前的权值。
题解:修改一个节点,子树上的其他节点都被修改,很像dfs序诶,实际上确实就是,但是这个不像前面一样一个区间里面一样的操作,它在区间里的操作有的是加val,有的是减val,这该如何是好呢。其实考虑到对于一个子树,一层是加,一层是减,一层加,一层减,这样的,所以可以对每一层的节点,设置一个col值,对于整棵树,偶数层的节点col=1,奇数层的节点col=0,然后更新的时候,如果是对奇数层的节点更新,那么把val=−val,因为奇数层是需要+val,但是由于奇数层节点的col=−1,所以需要把val变为负的,再相乘,col等于一个符号的作用吧,偶数层不变,然后最后查询时候返回的值为sum[rt]+add[rt]∗col[rt],其中sum为原来这个节点的值,add为后来加上去的值,col为这个节点的符号。
代码:
题意:给你一棵树,根节点1,每个节点有权值,然后你可以对一个节点进行操作,在它的权值上加上val,但是它的子节点需要加上−val,它的子节点的子节点就要加上−(−val),就是子节点加得的值和父节点相反,询问你某个节点当前的权值。
题解:修改一个节点,子树上的其他节点都被修改,很像dfs序诶,实际上确实就是,但是这个不像前面一样一个区间里面一样的操作,它在区间里的操作有的是加val,有的是减val,这该如何是好呢。其实考虑到对于一个子树,一层是加,一层是减,一层加,一层减,这样的,所以可以对每一层的节点,设置一个col值,对于整棵树,偶数层的节点col=1,奇数层的节点col=0,然后更新的时候,如果是对奇数层的节点更新,那么把val=−val,因为奇数层是需要+val,但是由于奇数层节点的col=−1,所以需要把val变为负的,再相乘,col等于一个符号的作用吧,偶数层不变,然后最后查询时候返回的值为sum[rt]+add[rt]∗col[rt],其中sum为原来这个节点的值,add为后来加上去的值,col为这个节点的符号。
代码:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; #define MAX 200005 #define MAXN 6005 #define maxnode 15 #define sigma_size 30 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,int> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; const double pi = acos(-1.0); //const double inf = 1e18; const double eps = 1e-8; const LL mod = 1e9+7; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ struct Edge{ int v,next; }edge[MAX*2]; int head[MAX]; int tot; int c[MAX]; int p1[MAX]; int p2[MAX]; int dep[MAX]; int ti; int dfsnum[MAX]; LL sum[MAX<<2]; int col[MAX<<2]; int add[MAX<<2]; void init(){ mem(head,-1); tot=0;ti=0; } void add_edge(int a,int b){ edge[tot]=(Edge){b,head[a]}; head[a]=tot++; } void dfs(int u,int fa,int d){ p1[u]=++ti; dep[u]=d; dfsnum[ti]=u; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa) continue; dfs(v,u,d+1); } p2[u]=ti; } void pushdown(int rt){ if(add[rt]){ add[lrt]+=add[rt]; add[rrt]+=add[rt]; add[rt]=0; } } void build(int l,int r,int rt){ add[rt]=0; if(l==r){ sum[rt]=c[dfsnum[l]]; if(dep[dfsnum[l]]&1) col[rt]=-1; else col[rt]=1; return; } middle; build(lson); build(rson); } void update(int l,int r,int rt,int L,int R,int d){ if(L<=l&&r<=R){ add[rt]+=d; return; } middle; pushdown(rt); if(L<=m) update(lson,L,R,d); if(R>m) update(rson,L,R,d); } int query(int l,int r,int rt,int pos){ if(l==r){ return sum[rt]+add[rt]*col[rt]; } middle; pushdown(rt); if(pos<=m) return query(lson,pos); else return query(rson,pos); } int main(){ //freopen("in.txt","r",stdin); int n,m; while(cin>>n>>m){ init(); for(int i=1;i<=n;i++) scanf("%d",&c[i]); for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } dfs(1,-1,0); build(1,n,1); //for(int i=1;i<=n;i++) cout<<p1[i]<<endl; while(m--){ int op,a; scanf("%d%d",&op,&a); if(op==1){ int val; scanf("%d",&val); if(dep[a]&1) val=-val; update(1,n,1,p1[a],p2[a],val); //for(int i=1;i<=n;i++){ cout<<query(1,n,1,p1[i])<<" ";} //cout<<endl; } else printf("%d\n",query(1,n,1,p1[a])); } } return 0; }
相关文章推荐
- VMware下安装CentOS 6安装教程图文详解
- linux 面试题总结
- Open-E DSS V7 应用系列之九 主动/主动 iSCSI群集部署(一)
- Linux基础命令操作(二)--文件权限与目录配置
- 如何使用API创建OpenStack虚拟机?
- Linux基础命令的操作(一)之基本操作
- Linux下yum命令详解
- docker的一些命令
- 用OpenCV对视频进行截图
- linux解压 tar命令
- 给OpenCV(2.x)增加汉字输出功能
- 20135218 Linux 实践二 编译模块
- Linux 免密码登录
- 强悍的 Linux —— 强悍的 vim (二)
- (已解决scientificlinux 与windows7的双系统问题)在linux下修复/添加windows启动/引导项
- linux gcc编译undefined reference to `stricmp'问题
- MFC Drag & Drop
- linux wc命令
- ps pstree kill top killall 命令
- 监控进程是否存在