BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
题意分析
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
首先上来两次dfs树链剖分问题不大,然后主要是这三个操作分别如何取实现。
先说第一种,点权修改,直接用线段树的点更新就好了。第二个子树修改,貌似树链剖分不能解决子树问题,但是仔细想一下其实是可以的,因为对任意一个节点x,其子树的节点编号都是连续的,原因是在dfs的时候,我们优先遍历这个节点的重儿子形成重链,其次遍历轻儿子形成轻链,所以他的儿子们是连续存储的。而需要修改的区间是[newid[x],newid[x]+size[x]-1],这样利用线段树的区间更新就可已解决了。最后一个询问操作,利用线段树的区间和,完美解决。
直的注意的一点是,在点更新的时候,别忘记有PushDown操作,因为已经打上了lazy标记
代码总览
#include <bits/stdc++.h>
#define ll long long
#define nmax 200820
using namespace std;
int fa[nmax],son[nmax],sz[nmax],newid[nmax],hashback[nmax],dep[nmax],top[nmax],newout[nmax];
int num,tot,head[nmax];
ll data[nmax];
struct edge{
int to;
int next;
}edg[nmax<<2];
struct tre{
int l,r;
ll val,lazy;
int mid(){
return (l+r)>>1;
}
}tree[nmax<<2];
void add(int u, int v){
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
void dfsFirst(int rt, int f,int d){
dep[rt] = d;
fa[rt] = f;
sz[rt] = 1;
for(int i = head[rt]; i!= -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != f){
dfsFirst(nxt,rt,d+1);
sz[rt]+=sz[nxt];
if(son[rt] == -1 || sz[nxt] > sz[son[rt]]){
son[rt] = nxt;
}
}
}
}
void dfsSecond(int rt, int tp){
top[rt] = tp;
newid[rt] = ++num;
hashback[num] = rt;
if(son[rt] == -1) return;
dfsSecond(son[rt],tp);
for(int i = head[rt];i != -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != son[rt] && nxt != fa[rt])
dfsSecond(nxt,nxt);
}
}
void init(){
memset(tree,0,sizeof tree);
memset(head,-1,sizeof head);
memset(son,-1,sizeof son);
memset(edg,0,sizeof edg);
memset(hashback,0,sizeof hashback);
memset(data,0,sizeof data);
memset(newid,0,sizeof newid);
tot = num = 0;
}
void PushUp(int rt){
tree[rt].val = tree[rt<<1].val + tree[rt<<1|1].val;
}
void PushDown(int rt){
if(tree[rt].lazy){
tree[rt<<1].lazy += tree[rt].lazy;
tree[rt<<1|1].lazy += tree[rt].lazy;
tree[rt<<1].val += tree[rt].lazy*(ll)(tree[rt<<1].r - tree[rt<<1].l + 1);
tree[rt<<1|1].val +=tree[rt].lazy*(ll)(tree[rt<<1|1].r - tree[rt<<1|1].l + 1);
tree[rt].lazy = 0;
}
}
void Build(int l, int r, int rt){
tree[rt].l = l; tree[rt].r = r;
if(l == r){
tree[rt].val = data[hashback[l]];
return;
}
Build(l,tree[rt].mid(),rt<<1);
Build(tree[rt].mid()+1,r,rt<<1|1);
PushUp(rt);
}
void UpdatePoint(ll val, int pos, int rt){
if(tree[rt].l == tree[rt].r){
tree[rt].val += (ll)val;
return;
}
PushDown(rt);
if(pos <= tree[rt].mid()) UpdatePoint(val,pos,rt<<1);
else UpdatePoint(val,pos,rt<<1|1);
PushUp(rt);
}
void UpdateInterval(ll val, int l, int r, int rt){
if(tree[rt].l >r || tree[rt].r < l) return;
if(tree[rt].l >= l && tree[rt].r <= r){
tree[rt].val += val*(ll)(tree[rt].r - tree[rt].l +1);
tree[rt].lazy += val;
return;
}
PushDown(rt);
UpdateInterval(val,l,r,rt<<1) ;
UpdateInterval(val,l,r,rt<<1|1);
PushUp(rt);
}
ll QuerySUM(int l,int r,int rt){
if(l>tree[rt].r || r<tree[rt].l) return 0;
PushDown(rt);
if(l <= tree[rt].l && tree[rt].r <= r) return tree[rt].val;
return QuerySUM(l,r,rt<<1) + QuerySUM(l,r,rt<<1|1);
}
ll Find_SUM(int x, int y){
int tx = top[x],ty =top[y];
ll ans = 0ll;
while(tx != ty){
if(dep[tx] < dep[ty]){
swap(x,y);
swap(tx,ty);
}
ans += QuerySUM(newid[tx],newid[x],1);
x = fa[tx]; tx = top[x];
}
if(dep[x] > dep[y]) swap(x,y);
ans += QuerySUM(newid[x],newid[y],1);
return ans;
}
int n,m;
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d %d",&n,&m)!=EOF){
init();
for(int i =1;i<=n;++i) scanf("%lld", &data[i]);
int u,v,x,y;
int op;
for(int i =1;i<=n-1;++i){
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfsFirst(1,0,1);
dfsSecond(1,1);
Build(1,n,1);
ll val;
for(int i = 0;i<m;++i){
scanf("%d",&op);
if(op == 1){// x add y
scanf("%d %lld",&x,&val);
UpdatePoint(val,newid[x],1);
}else if(op == 2){//x root add y
scanf("%d %lld",&x,&val);
UpdateInterval(val,newid[x],newid[x]+sz[x]-1,1);
}else{// query (1,x)
scanf("%d",&x);
printf("%lld\n",Find_SUM(1,x));
}
}
}
return 0;
}
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )的更多相关文章
- bzoj 4034 [HAOI2015]树上操作 入栈出栈序+线段树 / 树剖 维护到根距离和
题目大意 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- fzu 2082 过路费 (树链剖分+线段树 边权)
Problem 2082 过路费 Accept: 887 Submit: 2881Time Limit: 1000 mSec Memory Limit : 32768 KB Proble ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
随机推荐
- CSS3实现垂直居中的新方法
测试地址: http://codepen.io/anon/pen/PZKZqe 兼容性:
- Netty源码分析第3章(客户端接入流程)---->第1节: 初始化NioSockectChannelConfig
Netty源码分析第三章: 客户端接入流程 概述: 之前的章节学习了server启动以及eventLoop相关的逻辑, eventLoop轮询到客户端接入事件之后是如何处理的?这一章我们循序渐进, 带 ...
- ACM中常见错误提示解析
Output Limit Exceeded 多数发生在递归遍历的过程中,多输出了一些内容(比如说空格).Output Limit Exceeded还指如果输入某一组数据,你的程序返回的结果是一直输出某 ...
- 配置tensorflow环境(anaconda+jupyter notebook)
很早之前,tensorflow环境之前我也曾装过,但是用的不是很舒服,很多问题都不明所以然.今天想要系统地学习一下tensorflow,于是又重新搭建了一遍,这次还是踩了不少坑.特此写下此文,供有兴趣 ...
- Java之JSP和Servlet基础知识
JSP基础 JSP起源 JSP,JavaServer Pager的简称.由SUN倡导并联合其它公司创建. JSP是一门脚本语言 JSP可以嵌入到HTML中 JSP拥有Java语言的所有特性 面向对象. ...
- 20172319 实验三 《敏捷开发与XP实践》 实验报告
20172319 2018.05.17-30 实验三 <敏捷开发与XP实践> 实验报告 课程名称:<程序设计与数据结构> 学生班级:1723班 学生姓名:唐才铭 学生学号:20 ...
- TCP/IP,HTTP,HTTPS,WEBSocket协议
我看看着挺多的,我暂时没时间自己写,有需要的请借鉴 http://mp.weixin.qq.com/s?__biz=MzI0MDQ4MTM5NQ==&mid=2247486927&id ...
- WPF里面制作圆角文本框
转自:http://www.cnblogs.com/mengxin523/archive/2010/04/04/1704448.html 本以为WPF里面的XAML会很强大,可以设置很多属性,比如文本 ...
- js作用域相关笔记
1.js引擎.编译器.作用域. 引擎:负责JS全过程的编译和执行: 编译器:负责语法分析和代码生成: 作用域:负责收集并维护声明组成的查询,以及当前执行代码对这些变量的访问权限(简言之,作用域就是用于 ...
- sql中Union和union all的使用
该文转载自:http://www.cnblogs.com/chaobaojun/archive/2009/12/24/1631508.html 在MS-SQL如果将两个或更多查询的结果组合为单个结果集 ...