CodeForces 384E Propagating tree (线段树+dfs)
题意:题意很简单么,给定n个点,m个询问的无向树(1为根),每个点的权值,有两种操作,
第一种:1 x v,表示把 x 结点加上v,然后把 x 的的子结点加上 -v,再把 x 的子结点的子结点加上 -(-v),依次。。。
第二种:2 x, 表示查询 x 结点的权值。
析:因为这是一棵树,很难维护,所以可以考虑先用 dfs 记录每个结点的开始和结束的时间戳,而位于开始和结束时间戳内的就是就是它的子孙结点,
这样就能维护两棵线段树,一棵是奇数层的, 一棵是偶数层的,每次执行 1 操作就把相应的结点的开始和结束作为一个区间进行更新,然后再执行
相反层的 -v 进行更新。当查询的时候,就直接输出相应层的输出再加原来权值即可。
代码如下:
- #pragma comment(linker, "/STACK:1024000000,1024000000")
- #include <cstdio>
- #include <string>
- #include <cstdlib>
- #include <cmath>
- #include <iostream>
- #include <cstring>
- #include <set>
- #include <queue>
- #include <algorithm>
- #include <vector>
- #include <map>
- #include <cctype>
- #include <cmath>
- #include <stack>
- #include <sstream>
- #define debug() puts("++++");
- #define gcd(a, b) __gcd(a, b)
- #define lson l,m,rt<<1
- #define rson m+1,r,rt<<1|1
- #define freopenr freopen("in.txt", "r", stdin)
- #define freopenw freopen("out.txt", "w", stdout)
- using namespace std;
- typedef long long LL;
- typedef unsigned long long ULL;
- typedef pair<int, int> P;
- const int INF = 0x3f3f3f3f;
- const LL LNF = 1e16;
- const double inf = 0x3f3f3f3f3f3f;
- const double PI = acos(-1.0);
- const double eps = 1e-8;
- const int maxn = 200000 + 10;
- const int mod = 1000000007;
- const int dr[] = {-1, 0, 1, 0};
- const int dc[] = {0, 1, 0, -1};
- const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
- int n, m;
- const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- inline bool is_in(int r, int c){
- return r >= 0 && r < n && c >= 0 && c < m;
- }
- int dfsnum[maxn], in[maxn];
- int a[maxn], out[maxn], dep[maxn];
- int sum[2][maxn<<2], addv[2][maxn<<2];
- vector<int> G[maxn];
- int cnt;
- void dfs(int u, int fa, int d){
- dep[u] = d;
- in[u] = ++cnt;
- for(int i = 0; i < G[u].size(); ++i){
- int v = G[u][i];
- if(v == fa) continue;
- dfs(v, u, d+1);
- }
- out[u] = cnt;
- }
- void push_down(int *sum, int rt, int *addv){
- if(addv[rt] == 0) return ;
- int l = rt<<1, r = rt<<1|1;
- sum[l] += addv[rt];
- sum[r] += addv[rt];
- addv[l] += addv[rt];
- addv[r] += addv[rt];
- addv[rt] = 0;
- }
- void update(int *sum, int *addv, int L, int R, int val, int l, int r, int rt){
- if(L <= l && r <= R){
- addv[rt] += val;
- sum[rt] += val;
- return ;
- }
- push_down(sum, rt, addv);
- int m = l + r >> 1;
- if(L <= m) update(sum, addv, L, R, val, lson);
- if(R > m) update(sum, addv, L, R, val, rson);
- }
- int query(int *sum, int *addv, int M, int l, int r, int rt){
- if(l == r) return sum[rt];
- push_down(sum, rt, addv);
- int m = l + r >> 1;
- if(M <= m) return query(sum, addv, M, lson);
- return query(sum, addv, M, rson);
- }
- 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);
- G[u].push_back(v);
- G[v].push_back(u);
- }
- dfs(1, -1, 1);
- while(m--){
- int x, c, op;
- scanf("%d %d", &op, &x);
- int t = dep[x]&1;
- if(op == 1){
- scanf("%d", &c);
- update(sum[t], addv[t], in[x], out[x], c, 1, n, 1);
- if(in[x] < out[x])
- update(sum[t^1], addv[t^1], in[x]+1, out[x], -c, 1, n, 1);
- }
- else printf("%d\n", query(sum[t], addv[t], in[x], 1, n, 1) + a[x]);
- }
- return 0;
- }
CodeForces 384E Propagating tree (线段树+dfs)的更多相关文章
- codeforces 383C Propagating tree 线段树
http://codeforces.com/problemset/problem/383/C 题目就是说, 给一棵树,将一个节点的值+val, 那么它的子节点都会-val, 子节点的子节点+val. ...
- Codeforces 383C Propagating tree, 线段树, 黑白染色思想
按深度染色,奇深度的点存反权值. #include <bits/stdc++.h> using namespace std; vector <]; ],a[],s[],vis[],i ...
- Codeforces 383C . Propagating tree【树阵,dfs】
标题效果: 有一棵树,有两种操作模式对本树:1:表示为(1 x val),在NOx加在节点上val,然后x每个节点加上儿子- val.给每个儿子一个儿子在一起-(- val),加到没有儿子为止.2:表 ...
- CF620E New Year Tree 线段树 dfs序
luogu链接 题目大意: 有一个节点有颜色的树 操作1.修改子树的颜色 操作2.查询子树颜色的种类 注意,颜色种类小于60种 只有子树的操作,dfs序当然是最好的选择 dfs序列是什么,懒得讲了,自 ...
- CF620E New Year Tree 线段树+dfs序+bitset
线段树维护 dfs 序是显然的. 暴力建 60 个线段树太慢,于是用 bitset 优化就好了 ~ code: #include <bits/stdc++.h> #define M 63 ...
- S - Query on a tree HDU - 3804 线段树+dfs序
S - Query on a tree HDU - 3804 离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...
- HDU 5692 线段树+dfs序
Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意 Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...
随机推荐
- 让camera实现类似cs第一人称视角旋转和位移
直接把这个脚本挂在摄像机上就可: using System.Collections; using System.Collections.Generic; using UnityEngine; /* * ...
- How To Uninstall Software Using The Ubuntu Command Line
How To Uninstall Software Using The Ubuntu Command Line Uninstall Ubuntu Software Using The Terminal ...
- 使用case语句给字体改变颜色
使用case语句给字体改变颜色 #!/bin/bash color(){ RED_COLOR='\E[1;31m' GREEN_COLOR='\E[1;32m' YELLOW_COLOR='\E[1; ...
- Java 8新增的日期、时间格式器
一 获取DateTimeFormatter对象的三种方式 直接使用静态常量创建DateTimeFormatter格式器 使用代码不同风格的枚举值来创建DateTimeFormatter格式器 根据模式 ...
- 2015 浙江省赛 H - May Day Holiday
H - May Day Holiday As a university advocating self-learning and work-rest balance, Marjar Universit ...
- webbrowser和js交互小结
一.实现WebBrowser内部跳转,阻止默认打开IE 1.引用封装好的WebBrowserLinkSelf.dll实现 public partial class MainWindow : Windo ...
- app中使用微信分享注意事项
1. 在微信公众平台开通一个微信公众号,https://mp.weixin.qq.com 2. 将自己制作好的已签名的app安装到手机上 3. 下载微信开放平台获取应用签名的apk--- gen ...
- delphi 蓝牙 TBluetoothLE
delphi 蓝牙 TBluetoothLE.TBluetoothLEManager BLE http://docwiki.embarcadero.com/RADStudio/Seattle/en/U ...
- 部署和调优 2.7 mysql主从配置-1
MySQL 主从(MySQL Replication),主要用于 MySQL 的时时备份或者读写分离.在配置之前先做一下准备工作,配置两台 mysql 服务器,如果你的机器不能同时跑两台 Linux虚 ...
- adb pull 和 adb push
1. 操作单个文件 通过adb push,则可将文件添加到SD卡中.如果想在push的时候修改文件名称的话,只需要修改push的第二个参数改成完整路径(目录+文件名),如/sdcard/test-0. ...