BZOJ4034 [HAOI2015]树上操作+DFS序+线段树
参考:https://www.cnblogs.com/liyinggang/p/5965981.html
题意:是一个数据结构题,树上的,用dfs序,变成线性的;
思路:对于每一个节点x,记录其DFS序,包括第一次到的序号,用in【x】记录,离开的序号out【x】记录,
再开一个数组seg,in:(序号——>节点的值);out:(序号——>节点的负值);
这样就可以使得
对于树来说:若所求的一个区间完全包含一个不相关子树,这个子树对结果不影响;
对于基于 线性 的线段树来说,同时包含in【x】、out【x】区间,区间求和为0;
利用线段树build 数组seg,得到区间的加和;
所以,
1-->分别更新in【x】,out【x】所对应的值;
2-->update in【x】到out【x】区间的值;
3-->返回 1 (根) 到 in【x】 区间的即可;
#include <iostream>
#include <cstdio>
#include <vector>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn = ;
ll sum[maxn*];
ll seg[maxn],a[maxn],lazy[maxn*],flag[maxn*];
ll in[maxn],out[maxn];
ll io[maxn];
int cnt = ;
int n,m;
vector <int> mp[maxn];
void dfs(int u,int fa)
{
cnt++;
seg[cnt] = 1ll*a[u],in[u] = 1ll*cnt;
for(int i=; i< mp[u].size(); i++)
{
int tmp = mp[u][i];
if(tmp == fa)continue;
dfs(tmp,u);
}
cnt++;
seg[cnt] = -1ll*a[u],out[u] = 1ll*cnt;
io[cnt] = -;
}
void pushup(int rt)
{
sum[rt] = sum[rt<<] + sum[rt<<|];
flag[rt] = flag[rt<<] + flag[rt<<|];
}
void pushdown(int rt)
{
if(lazy[rt])
{
lazy[rt<<] += lazy[rt];
lazy[rt<<|]+= lazy[rt];
sum[rt<<] += flag[rt<<] * lazy[rt];
sum[rt<<|] += flag[rt<<|]*lazy[rt];
lazy[rt] = ;
}
}
void build(int rt,int l,int r)
{
if(l==r)
{
sum[rt] = seg[l];
if(io[l]==)flag[rt] = ;
else flag[rt] = -;
return ;
}
int mid = (l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
pushup(rt);
}
void update_one(int pos,int d,int l,int r,int rt)//单点更新;
{
if(l == r)
{
if(flag[rt] == )
sum[rt] += d;
else sum[rt] -= d;
return;
}
pushdown(rt);
int mid = (l+r)>>;
if(pos<=mid) update_one(pos,d,l,mid,rt<<);
else update_one(pos,d,mid+,r,rt<<|);
pushup(rt);
}
void update_d(int L,int R,int d,int l,int r,int rt)//区间更新;
{
if(l >= L && R >= r)
{
sum[rt] += flag[rt]*d;
lazy[rt] += d;
return;
}
pushdown(rt);
int mid = (l+r)>>;
if(L<=mid) update_d(L,R,d,l,mid,rt<<);
if(R>mid) update_d(L,R,d,mid+,r,rt<<|);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt)//区间查询
{
if(l>=L&&r<=R)
{
return sum[rt];
}
int mid = (l+r)>>;
ll res = ;
pushdown(rt);
if(mid>=L)res += query(L,R,l,mid,rt<<);
if(mid<R)res +=query(L,R,mid+,r,rt<<|);
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=; i<=n;i++)
{
scanf("%lld" ,&a[i]);
} for(int i=; i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
mp[v].pb(u);
mp[u].pb(v);
}
dfs(,);
build(,,*n);
for(int i= ;i <= m; i++)
{
int op,x,val;
scanf("%d", &op);
if(op==) {
scanf("%d%d",&x,&val);
update_one(in[x],val,,*n,);
update_one(out[x],val,,*n,);
}
else if(op==) {
scanf("%d%d",&x,&val);
update_d(in[x],out[x],val,,*n,);
}
else if(op==) {
scanf("%d",&x);
printf("%lld\n",query(,in[x],,*n,));
}
}
return ;
}
BZOJ4034 [HAOI2015]树上操作+DFS序+线段树的更多相关文章
- [bzoj3306]树——树上倍增+dfs序+线段树
Brief Description 您需要写一种数据结构,支持: 更改一个点的点权 求一个子树的最小点权 换根 Algorithm Design 我们先忽略第三个要求. 看到要求子树的最小点权,我们想 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树上分块+dfs序+线段树)
题意 链接:https://nanti.jisuanke.com/t/A1998 给出一个有根树(根是1),有n个结点.初始的时候每个结点的值都是0.下面有q个操作,操作有两种,操作1.将深度为L(根 ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
- [luoguP3178] [HAOI2015]树上操作(dfs序 + 线段树 || 树链剖分)
传送门 树链剖分固然可以搞. 但还有另一种做法,可以看出,增加一个节点的权值会对以它为根的整棵子树都有影响,相当于给整棵子树增加一个值. 而给以某一节点 x 为根的子树增加一个权值也会影响当前子树,节 ...
- 牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)
牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) 链接:https://ac.nowcoder.com/acm/problem/15706 现在需要您来帮忙维护这个名册, ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- BZOJ1103 [POI2007]大都市meg dfs序 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...
- Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- HDU.5692 Snacks ( DFS序 线段树维护最大值 )
HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...
随机推荐
- Java 字符串分隔 split
Java中的我们可以利用 split 方法(Java.lang.string.split)把字符串按照指定的分割符进行分割,然后返回字符串数组,下面是string.split的用法实例及注意事项. s ...
- Vue2.0仿饿了么webapp单页面应用
Vue2.0仿饿了么webapp单页面应用 声明: 代码源于 黄轶老师在慕课网上的教学视频,我自己用vue2.0重写了该项目,喜欢的同学可以去支持老师的课程:http://coding.imooc.c ...
- UR机器人的位姿
一.Ur 移动命令 UR机器人移动,一共有三种移动指令,movej,movel,movep,分别是关节运动,线性运动,圆周运动. movej:6个关节的弧度 movel/movep:分别是x,y,z, ...
- java课堂_动手动脑4
1.请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? 答:在Java中,内容相同的字串常量(“Hello”)只保存一份以节约内存,所以s0 ...
- 关于dfs的套路
void dfs(答案, 搜索层数, 其他参数) { if (层数==maxdeep) { 更新答案 return; } (剪枝) for(下一层可能的状态){ 更新全局变量表示的状态的变量 dfs( ...
- gdb调试和编译后运行结果不一致
今天在看代码时,遇到这么一段代码,我但是用g++编译了,运行发现有Segmentation fault. 然后就用gdb跟进去看看,可是gdb却正常执行了.不知道什么原因. #include < ...
- spark shuffle读操作
提出问题 1. shuffle过程的数据是如何传输过来的,是按文件来传输,还是只传输该reduce对应在文件中的那部分数据? 2. shuffle读过程是否有溢出操作?是如何处理的? 3. shuff ...
- 图解SSH隧道功能
SSH能够对SSH客户端与服务器端之间的网络通信提供加密功能,而且SSH的端口转发功能还能将其它TCP端口的网络数据通过SSH连接来转发,并且自动提供相应的加密和解密服务,这一过程也被称为“隧道”(t ...
- jmh源码解析-整体架构
我理解的jmh运行架构图 生成字节码,字节码负责维护测试的状态和调用被测试的方法 默认在fork的进程中进行测试,可以配置多个fork进程,以减少误差 通过线程池,提交每个迭代的测试任务,任务执行后, ...
- LeetCode——540. Single Element in a Sorted Array
题目:Given a sorted array consisting of only integers where every element appears twice except for one ...