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号 ...
随机推荐
- 【iOS】PrefixHeader.pch
还不太理解,暂且记下.
- Java编程思想之十七 容器深入研究
17.1 完整的容器分类方法 17.2 填充容器 import java.util.*; class StringAddress { private String s; public StringAd ...
- web图形验证码逻辑
逻辑:前端生成一个UUID以URL方式发送给后端,后端准备Redis数据库缓存数据,后端拿到UUID后,调用captcha.generate_captcha()生成图片和图片的标签,Redis数据库保 ...
- Spring源码解析——循环依赖的解决方案
一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...
- C#中属性的解析
一.域的概念 C#中域是指成员变量和方法,在OOP编程中(面向对象编程)我们要求用户只知道类是干什么的,而不许知道如何完成的,或者说不允许访问类的内部,对于有必要在类外可见的域,我们用属性来表达,所以 ...
- C语言编程入门之--第五章C语言基本运算和表达式-part1
导读:程序要完成高级功能,首先要能够做到基本的加减乘除.本章从程序中变量的概念开始,结合之前学的输出函数和新介绍的输入函数制作简单人机交互程序,然后讲解最基础的加减法运算,自制简单计算器程序练手. 5 ...
- RE最全面的正则表达式----终结篇 特殊处理
三.特殊需求表达式 Email地址:^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0- ...
- 压力测试-jmeter
1. 场景描述 新申请的服务器,要压测下python算法程序最多能执行多少条数据,有几年没用压力测试工具-jmeter了,重新下载了最新版本,记录下,也希望能帮到准备使用jmeter做压测的朋友. 2 ...
- 洛谷 P3628 特别行动队
洛谷题目页面传送门 题意见洛谷. 这题一看就是DP... 设\(dp_i\)表示前\(i\)个士兵的最大战斗力.显然,最终答案为\(dp_n\),DP边界为\(dp_0=0\),状态转移方程为\(dp ...
- JVM类生命周期概述:加载时机与加载过程
一个.java文件在编译后会形成相应的一个或多个Class文件,这些Class文件中描述了类的各种信息,并且它们最终都需要被加载到虚拟机中才能被运行和使用.事实上,虚拟机把描述类的数据从Class文件 ...