https://www.lydsy.com/JudgeOnline/problem.php?id=4034

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
 
dfs序真是一个奥妙重重的东西
首先求出dfs序,操作1显然是一个单点修改,操作2显然是一个区间修改,我们看到我们要询问的事实上是一条链的和,我们就不能简单地进行单点修改和区间修改,事实上1到x的点在dfs序上可以视为一个栈,第一次出现是进栈,第二次出现时出栈,我们只要将进栈的点权为正,出栈的点权为负,线段树进行一波区间修改和区间查询即可。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 4e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
LL val[maxn];
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],tot;
void init(){Mem(head,-); tot = ;}
void add(int u,int v){edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++;}
PII Index[maxn * ];
PII pos[maxn];
int id = ;
void dfs(int t,int fa){
Index[++id].fi = t;
Index[id].se = ;
pos[t].fi = id;
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == fa) continue;
dfs(v,t);
}
Index[++id].fi = t;
Index[id].se = -;
pos[t].se = id;
}
struct Tree{
int l,r;
int up,down;
LL sum,lazy;
}tree[maxn << ];
void Pushup(int t){
tree[t].sum = tree[t << ].sum + tree[t << | ].sum;
}
void Build(int t,int l,int r){
tree[t].l = l; tree[t].r = r;
tree[t].up = tree[t].down = tree[t].lazy = ;
if(l == r){
if(Index[l].se == ){
tree[t].sum = val[Index[l].fi];
tree[t].up++;
}else{
tree[t].sum = -val[Index[l].fi];
tree[t].down++;
}
return ;
}
int m = (l + r) >> ;
Build(t << ,l,m); Build(t << | ,m + ,r);
Pushup(t);
tree[t].up = tree[t << ].up + tree[t << | ].up;
tree[t].down = tree[t << ].down + tree[t << | ].down;
}
void Pushdown(int t){
if(tree[t].lazy){
tree[t << ].sum += (tree[t << ].up - tree[t << ].down) * tree[t].lazy;
tree[t << | ].sum += (tree[t << | ].up - tree[t << | ].down) * tree[t].lazy;
tree[t << ].lazy += tree[t].lazy; tree[t << | ].lazy += tree[t].lazy;
tree[t].lazy = ;
}
}
void update(int t,int l,int r,LL a){
if(l <= tree[t].l && tree[t].r <= r){
tree[t].sum += (tree[t].up - tree[t].down) * a;
tree[t].lazy += a;
return;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) update(t << ,l,r,a);
else if(l > m) update(t << | ,l,r,a);
else{
update(t << ,l,m,a);
update(t << | ,m + ,r,a);
}
Pushup(t);
}
LL query(int t,int l,int r){
if(l > r) return ;
if(l <= tree[t].l && tree[t].r <= r){
return tree[t].sum;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) return query(t << ,l,r);
else if(l > m) return query(t << | ,l,r);
else{
return query(t << ,l,m) + query(t << | ,m + ,r);
}
}
int main()
{
Sca2(N,M); init();
For(i,,N) Scl(val[i]);
For(i,,N - ){ int u,v; Sca2(u,v); add(u,v); add(v,u);}
int root = ; id = ;
dfs(root,-);
Build(,, * N);
while(M--){
int op = read();
if(op == ){
int x; Sca(x); LL a; Scl(a);
update(,pos[x].fi,pos[x].fi,a); update(,pos[x].se,pos[x].se,a);
}else if(op == ){
int x; Sca(x); LL a; Scl(a);
update(,pos[x].fi,pos[x].se,a);
}else{
int x; Sca(x);
Prl(query(,,pos[x].fi));
}
}
#ifdef VSCode
system("pause");
#endif
return ;
}

bzoj4034 线段树+dfs序的更多相关文章

  1. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  2. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  3. 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序

    题目大意 ​ Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...

  4. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  5. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  6. HDU 5692 线段树+dfs序

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  7. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  8. 【BZOJ-3306】树 线段树 + DFS序

    3306: 树 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 792  Solved: 262[Submit][Status][Discuss] De ...

  9. HDU5692(线段树+dfs序)

    Snacks Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Statu ...

随机推荐

  1. H5 history.pushState 在微信内修改url后点击用safari打开/复制链接是修改之前的页面

    解决方案:url参数增加随机参数 function wxRefresh() { var replaceQueryParam = (param, newval, search) => { var ...

  2. POJ 3349-Snowflake Snow Snowflakes-字符串哈希

    哈希后,对每片雪花对比6次. #include <cstdio> #include <cstring> #include <vector> #include < ...

  3. python基础成长之路三

    1,基础数据类型 总览 int :数字  用于计数,计算,运算等...1 , 2 , 3  , 100 , ... str :字符串  用户少量的数据储存,便于操作   "这就是字符串&qu ...

  4. Number Sequence POJ - 1019 递推 数学

    题意 1 12 123 1234 12345 ....这样的序列 问第n位数字是几   是数字! 1-9! 思路:递推关系 主要是位数的计算   用a[i]=a[i-1]+(int)log10((do ...

  5. 洛谷P3381 最小费用最大流

    费用流板子 还是一道板子题..先练练手 #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a, b) memset( ...

  6. [HDU4635] Strongly connected

    传送门:>Here< 题意:给出一张DAG,问最多添加几条边(有向)使其强连通分量个数大于1 解题思路 最少添加几条边使其强连通我们是知道的,非常简单,就是入度为0的点与出度为0的点的较大 ...

  7. atcoder NIKKEI Programming Contest 2019 E - Weights on Vertices and Edges

    题目链接:Weights on Vertices and Edges 题目大意:有一个\(n\)个点\(m\)条边的无向图,点有点权,边有边权,问至少删去多少条边使得对于剩下的每一条边,它所在的联通块 ...

  8. 【XSY2785】模型

    题目描述 给你一棵\(n\)个点的树,让你加最少的边,使得图中没有割点. 要求输出方案. \(n\leq 500000\) 题解 把叶子的权值设为\(1\),其他点设为\(0\),找出带权重心. 以重 ...

  9. day5 range 用法示例

    函数语法 range(start, stop[, step]) 参数说明: start: 计数从 start 开始.默认是从 0 开始.例如range(5)等价于range(0, 5); stop: ...

  10. vi编辑光标跳到文件开头和结尾以及清空文件命令

    vi编辑光标跳到文件开头和结尾以及清空文件命令 按esc退出编辑模式 跳到文件开头: :1 跳到文件结尾: :$ 清空文件内容: 小写的 d 加上大写的 G