参考: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序+线段树的更多相关文章

  1. [bzoj3306]树——树上倍增+dfs序+线段树

    Brief Description 您需要写一种数据结构,支持: 更改一个点的点权 求一个子树的最小点权 换根 Algorithm Design 我们先忽略第三个要求. 看到要求子树的最小点权,我们想 ...

  2. ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树上分块+dfs序+线段树)

    题意 链接:https://nanti.jisuanke.com/t/A1998 给出一个有根树(根是1),有n个结点.初始的时候每个结点的值都是0.下面有q个操作,操作有两种,操作1.将深度为L(根 ...

  3. 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)

    P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...

  4. [luoguP3178] [HAOI2015]树上操作(dfs序 + 线段树 || 树链剖分)

    传送门 树链剖分固然可以搞. 但还有另一种做法,可以看出,增加一个节点的权值会对以它为根的整棵子树都有影响,相当于给整棵子树增加一个值. 而给以某一节点 x 为根的子树增加一个权值也会影响当前子树,节 ...

  5. 牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树)

    牛客wannafly 挑战赛14 B 前缀查询(trie树上dfs序+线段树) 链接:https://ac.nowcoder.com/acm/problem/15706 现在需要您来帮忙维护这个名册, ...

  6. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  7. BZOJ1103 [POI2007]大都市meg dfs序 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1103 题意概括 一棵树上,一开始所有的边权值为1,我们要支持两种操作: 1. 修改某一条边的权值为 ...

  8. 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 ...

  9. HDU.5692 Snacks ( DFS序 线段树维护最大值 )

    HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...

随机推荐

  1. hdoj 3732 Ahui Writes Word (多重背包)

    之前在做背包的题目时看到了这道题,一看,大喜,这不是裸裸的01背包吗!!  然后华丽丽的超时,相信很多人也和我一样没有考虑到数据量的大小. 时隔多日,回过头来看这道题,依旧毫无头绪....不过相比之前 ...

  2. java在src/test/resourse下读取properties文件

    package com.jiepu; import java.io.File; import java.net.URISyntaxException; import java.util.Map; im ...

  3. 干货来了!python学习之重难点整理合辑1

    关于装饰器.lambda.鸭子类型.魔法函数的理解仍存有困惑之处,趁周末有时间温故,赶紧去自学了解下相关知识. 1.装饰器是什么: 很多初学者在接触装饰器的时候只做到了肤浅的了解它的概念.组成形态.实 ...

  4. drf之序列化

    在django视图中使用serializer 只是使用serializer类编写API视图,没有用到REST框架 app01下的models.py from django.db import mode ...

  5. react-native-gesture-handler报错

    安装React Native第三方组件出现Task :react-native-gesture-handler:compileDebugJavaWithJavac FAILED报错,则使用jetifi ...

  6. 在Vue 中使用Typescript

    Vue 中使用 typescript 什么是typescript typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法.它很像JavaScript都强类 ...

  7. springboot+支付宝条码支付开发详解

    背景:项目原有乐刷聚合支付,无法参加支付宝.微信等支付机构的官方活动 需求:增加原生支付(支付宝条码支付) 方法: 一.官方文档:https://docs.open.alipay.com/194/10 ...

  8. 二.安全NA之ASA基础

    一.ASA常用命令 show run interface #查看接口配置 show ip address #查看IP地址 show conn #查看防火墙状态信息,U代表up:I,代表进流量:O,代表 ...

  9. Day 03--设计与完善(一)

    1.今天我们把软件原型基本完成了,功能流程一套下来,像一个真正的软件了.这是几个主要模块: 首先是首页,登入小程序后可以直观地看到各个食堂,并显示自己的定位.屏幕下方还可以时刻切换查看自己以前的订单. ...

  10. win10下vc++6.0的安装问题

    由于最近需要在win10系统下用到vc++来编程(其实刚开始我是拒绝的,因为vc++各种坑),下面我就把安装vc++时遇到的问题记录下来,方便以后同样遇到这些问题的同学. 安装vc++6.0所需要东西 ...