bzoj 4034 [HAOI2015]树上操作 入栈出栈序+线段树 / 树剖 维护到根距离和
题目大意
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
分析
真就是一见到这类题就得先写一次,发现错,再写一次
想清楚再写行不 -.-
方法1:树剖
方法2:入栈出栈序
入栈+,出栈 -
一个点x到根路径和,就是sum[1,in[x]]
如何区间修改呢
线段树上记录区间中 +的个数减去 -的个数
就是一次修改中权值总体要增加多少个delta
具体见代码
solution
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int M=100007;
inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
}
LL val[M];
int n,m;
int g[M],te;
struct edge{
int y,nxt;
}e[M<<1];
void addedge(int x,int y){
e[++te].y=y;e[te].nxt=g[x];g[x]=te;
}
int st[M],ed[M],ty[M<<1],dd[M<<1],tdfn=0;
void dfs(int x,int fa){
st[x]=++tdfn;
ty[tdfn]=1;
dd[tdfn]=val[x];
int p,y;
for(p=g[x];p;p=e[p].nxt)
if((y=e[p].y)!=fa) dfs(y,x);
ed[x]=++tdfn;
ty[tdfn]=-1;
dd[tdfn]=-val[x];
}
struct seg{
LL sum,tag,sz;
}a[M<<3];
void pushup(int x){
a[x].sum=a[x<<1].sum+a[x<<1|1].sum;
}
void totag(int x,LL d){
a[x].sum+=d*a[x].sz;
a[x].tag+=d;
}
void pushdown(int x){
if(a[x].tag){
totag(x<<1,a[x].tag);
totag(x<<1|1,a[x].tag);
a[x].tag=0;
}
}
void build(int x,int l,int r){
if(l==r){
a[x].sum=dd[l];
a[x].sz=ty[l];
a[x].tag=0;
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
a[x].sz=a[x<<1].sz+a[x<<1|1].sz;
}
void add(int x,int l,int r,int tl,int tr,LL d){
if(tl<=l&&r<=tr){
totag(x,d);
return;
}
int mid=l+r>>1;
pushdown(x);
if(tl<=mid) add(x<<1,l,mid,tl,tr,d);
if(mid<tr) add(x<<1|1,mid+1,r,tl,tr,d);
pushup(x);
}
LL get(int x,int l,int r,int tl,int tr){
if(tl<=l&&r<=tr) return a[x].sum;
int mid=l+r>>1;
pushdown(x);
LL res=0;
if(tl<=mid) res+=get(x<<1,l,mid,tl,tr);
if(mid<tr) res+=get(x<<1|1,mid+1,r,tl,tr);
return res;
}
int main(){
int i,kd,x,y;
n=rd(); m=rd();
for(i=1;i<=n;i++) val[i]=rd();
for(i=1;i<n;i++){
x=rd(),y=rd();
addedge(x,y);
addedge(y,x);
}
dfs(1,0);
build(1,1,2*n);
while(m--){
kd=rd();
if(kd==1){
x=rd(); y=rd();
add(1,1,2*n,st[x],st[x],y);
add(1,1,2*n,ed[x],ed[x],y);
}
else if(kd==2){
x=rd(); y=rd();
add(1,1,2*n,st[x],ed[x],y);
}
else{
x=rd();
printf("%lld\n",get(1,1,2*n,1,st[x]));
}
}
return 0;
}
bzoj 4034 [HAOI2015]树上操作 入栈出栈序+线段树 / 树剖 维护到根距离和的更多相关文章
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6779 Solved: 2275[Submit][Stat ...
- [BZOJ]4034: [HAOI2015]树上操作
[HAOI2015]树上操作 传送门 题目大意:三个操作 1:a,b,c b节点权值+c 2:a,b,c 以b为根的子树节点权值全部+c 3:a,b 查询b到根路径的权值和. 题解:树链剖分 操作1 ...
- BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)
题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
- BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]
题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...
- 洛谷 P3178 BZOJ 4034 [HAOI2015]树上操作
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 ...
- BZOJ 4034 [HAOI2015]树上操作 线段树+树剖或dfs
题意 直接照搬原题面 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所 ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
随机推荐
- ssh整合思想 Spring与Hibernate和Struts2的action整合 调用action添加数据库 使用HibernateTemplate的save(entity)方法 update delete get 等方法crud操作
UserAction类代码: package com.swift.action; import com.opensymphony.xwork2.ActionSupport; import com.sw ...
- 关于OnTimer()使用
OnTimer()其实是用来响应WM_TIMER消息的,其实OnTimer()就是一个回调函数,不过是系统默认的,当用户使用SetTimer()函数设定一个定时器的时候,只要是第三个参数为NULL,则 ...
- GoogleTest 之路1-Generic Build Instructions编译指导总方案
准备工作 为了在你的测试中使用GoogleTest, 你必须让你的编译系统 知道到哪里去寻找GoogleTest 的头文件和源文件. 具体的方法只能依赖于你具体使用的哪种编译系统了,一般来讲这个非常容 ...
- python入门:输出1-10以内除去7的所有数(简)
#!/usr/bin/env python # -*- coding:utf-8 -*- #输出1-10以内除去7的所有数(简) """ 给变量kaishi赋值1,whi ...
- 20.Yii2.0框架多表关联一对多查询之hasMany
目录 新手模式 hasMany关联模式查询 新建mode层Article.php 新建mode层Category.php 新建控制器HomeController.php 新手模式 用上次的查询结果,作 ...
- CentOS 7.0 使用 yum 安装 MariaDB 及 简单配置
1.安装MariaDB 安装命令 yum -y install MariaDB-server MariaDB-client 安装完成MariaDB,首先启动MariaDB 设置开机启动 接下来进行Ma ...
- matlab画图颜色设置
各种颜色属性选项选项意义选项意义'r' 红色 'm' 粉红'g' 绿色 'c' 青色'b' 兰色 'w' 白色'y' 黄色 'k' 黑色各种线型属性选项选项意义选项意义'-' 实线 '--' 虚线': ...
- Solr 7 部署与使用踩坑全记录
前言 Solr 是一种可供企业使用的.基于 Lucene 的搜索服务器,它支持层面搜索.命中醒目显示和多种输出格式.在这篇文章中,我将介绍 Solr 的部署和使用的基本操作,希望能让初次使用的朋友们少 ...
- Java集合数据类型
Java集合如Map.Set.List等所有集合只能存放引用类型数据,它们都是存放引用类型数据的容器,不能存放如int.long.float.double等基础类型的数据. 1. 集合存储对象 Jav ...
- python - work5 - 类与对象 - 拓展题
''' 5:购物车类,包含的功能如下,请自行设计这个类以及类里面的方法:1)用户输入工资后,打印商品列表(商品列表自行设计展示模式)2)允许用户根据商品编号去选择商品3)用户选择商品后,检查余额是否足 ...