Codeforces Round #225 (Div. 1) C-Propagating tree (DFS序+线段树/树状数组)
2016-05-27 21:24
405 查看
题目链接:http://codeforces.com/contest/383/problem/C
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 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
Sample Output
3
3
0
题意:给出一颗有n个节点,且1为根节点的树,每个节点有它的权值,现在进行m次操作,操作分为添加和查询,当一个节点的权值添加v,则它的孩子节点的权值要添加-v。
题解:DFS标号后,按照深度分出奇偶层,当奇数(偶数)层+v时,对应偶数(奇数)层-v,两个线段树跑一跑就好。
线段树:
[b]树状数组:
Description
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 thetree 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 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
Sample Output
3
3
0
题意:给出一颗有n个节点,且1为根节点的树,每个节点有它的权值,现在进行m次操作,操作分为添加和查询,当一个节点的权值添加v,则它的孩子节点的权值要添加-v。
题解:DFS标号后,按照深度分出奇偶层,当奇数(偶数)层+v时,对应偶数(奇数)层-v,两个线段树跑一跑就好。
线段树:
//#include <bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define bug cout<<"bug"<<endl const int MAXN = 2e5+7; int n,m,index; int val[MAXN],lazy[2][MAXN<<2]; vector<int> node[MAXN]; int deep,L[MAXN],R[MAXN],flag[MAXN],id[MAXN]; void dfs(int u, int fa, int poi) { L[u]=++deep; id[deep]=u; flag[u]=poi; int siz=node[u].size(); for(int i=0; i<siz; ++i) { int v=node[u][i]; if(v==fa)continue; dfs(v,u,poi^1); } R[u]=deep; } /* void build(int l, int r, int poi) { if(l==r){lazy[0][poi]=lazy[1][poi]=val[id[l]];return;} int mid=(l+r)>>1; build(l,mid,poi<<1); build(mid+1,r,poi<<1^1); }*/ void push_data(int poi) { if(lazy[0][poi]) { lazy[0][poi<<1]+=lazy[0][poi]; lazy[0][poi<<1^1]+=lazy[0][poi]; } if(lazy[1][poi]) { lazy[1][poi<<1]+=lazy[1][poi]; lazy[1][poi<<1^1]+=lazy[1][poi]; } lazy[0][poi]=lazy[1][poi]=0; } void update(int l, int r, int a, int b, int poi, int f, int add) { if(a<=l && r<=b){lazy[f][poi]+=add;lazy[f^1][poi]-=add;return;} push_data(poi); int mid=(l+r)>>1; if(mid>=a)update(l,mid,a,b,poi<<1,f,add); if(mid<b)update(mid+1,r,a,b,poi<<1^1,f,add); } int query(int l, int r, int poi, int f, int p) { if(l==r)return lazy[f][poi]; push_data(poi); int mid=(l+r)>>1; if(mid>=p)return query(l,mid,poi<<1,f,p); return query(mid+1,r,poi<<1^1,f,p); } int main() { scanf("%d%d",&n,&m); index=0; for(int i=1; i<=n; ++i) scanf("%d",&val[i]); int a,b,c; for(int i=0; i<n-1; ++i) { scanf("%d%d",&a,&b); node[a].push_back(b); node.push_back(a); } deep=0; dfs(1,0,0); // build(1,n,1); for(int i=0; i<m; ++i) { scanf("%d%d",&a,&b); if(a==1) { scanf("%d",&c); update(1,n,L[b],R[b],1,flag[b],c); } else printf("%d\n",val[b]+query(1,n,1,flag[b],L[b])); } return 0; } /* 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 */
[b]树状数组:
//#include <bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define bug cout<<"bug"<<endl #define lowbit(a) a&(-a) const int MAXN = 2e5+7; int n,m,index; int val[MAXN],lazy[2][MAXN<<2]; vector<int> node[MAXN]; int deep,L[MAXN],R[MAXN],flag[MAXN],id[MAXN]; void dfs(int u, int fa, int poi) { L[u]=++deep; id[deep]=u; flag[u]=poi; int siz=node[u].size(); for(int i=0; i<siz; ++i) { int v=node[u][i]; if(v==fa)continue; dfs(v,u,poi^1); } R[u]=deep; } void add_data(int p, int f, int data) { int i=p; while(i<=n) { lazy[f][i]+=data; lazy[f^1][i]-=data; i+=lowbit(i); } } int query(int p, int f) { int i=p,ans=0; while(i>0) { ans+=lazy[f][i]; i-=lowbit(i); } return ans; } int main() { scanf("%d%d",&n,&m); index=0; for(int i=1; i<=n; ++i) scanf("%d",&val[i]); int a,b,c; for(int i=0; i<n-1; ++i) { scanf("%d%d",&a,&b); node[a].push_back(b); node[b].push_back(a); } deep=0; dfs(1,0,0); for(int i=0; i<m; ++i) { scanf("%d%d",&a,&b); if(a==1) { scanf("%d",&c); add_data(L[b],flag[b],c); add_data(R[b]+1,flag[b],-c); } else printf("%d\n",val[b]+query(L[b],flag[b])); } return 0; } /* 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 */
相关文章推荐
- linux基本命令(40)——wc命令
- Learning OpenCV:cvCvtColor and cvCanny
- Linux屏幕录像
- linux基本命令(39)——grep命令
- Spark 附带示例完整解释(原文已在IBM Developworks发表)
- Vim 高级用法 1 点的妙用
- linux
- bash 读取行
- linux下的简单文件读写锁的操作
- Learning OpenCV: cvPyrDown and display video
- [转]Kyoto Cabinet和LevelDB的架构比较分析
- TOPCODER SRM 686 div2 1000
- Learning OpenCV: cvSmooth processing
- 常用网站
- linux
- 73条日常Linux shell命令汇总
- bash 提示
- docker学习笔记2-docker入门
- Learning OpenCV: read video and add onTrackSlider
- Hadoop整合Hive之API封装及操作