[HAOI2015]树上操作(树链剖分)
Description
题目描述
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
- 操作 1 :把某个节点 x 的点权增加 a 。
- 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
- 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
输入格式
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
输出格式
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Solution
操作 1:线段树中点dfn[x]加a;
操作 2:由树链剖分遍历的顺序可知任何一棵子树中节点的dfs序<=子树的根的dfs序,
且最大的dfs序=子树的根的dfs序+子树的大小-1,于是可以直接在线段树上操作;
操作 3:简化版树剖求和模板
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
const int N=1e5+;
struct node
{
int l,r,lc,rc;
long long sum,delay;
}f[N*];
int n,u,v,m,deep[N],tot,si[N],top[N],d[N],t,
fa[N],dfn[N],cnt,rt,son[N],re[N],opt,x;
long long a;
char s[];
vector <int> link[N];
void dfs1(int u,int f)
{
si[u]=,fa[u]=f,deep[u]=deep[f]+;
int size=link[u].size();
for(int i=;i<size;i++)
{
int v=link[u][i];
if(v!=f)
{
dfs1(v,u);
si[u]+=si[v];
if(son[u]== || si[son[u]]<si[v]) son[u]=v;
}
}
}
void dfs2(int u,int f)
{
dfn[u]=++tot,re[tot]=u;
if(son[u]!=)
{
top[son[u]]=top[u],dfs2(son[u],u);
int size=link[u].size();
for(int i=;i<size;i++)
{
int v=link[u][i];
if(v!=f && v!=son[u])
top[v]=v,dfs2(v,u);
}
}
}
long long gel(int g)
{
return f[g].r-f[g].l+;
}
void push_up(int g)
{
int lc=f[g].lc,rc=f[g].rc;
if(lc==) return ;
f[g].sum=f[lc].sum+f[rc].sum+gel(g)*f[g].delay;
}
void push_down(int g)
{
int lc=f[g].lc,rc=f[g].rc;
if(lc== || f[g].delay==) return ;
f[lc].delay+=f[g].delay,f[rc].delay+=f[g].delay;
f[lc].sum+=gel(lc)*f[g].delay,f[rc].sum+=gel(rc)*f[g].delay;
f[g].delay=;
}
void build(int &g,int l,int r)
{
g=++cnt;
f[g].l=l,f[g].r=r;
if(l==r)
{
f[g].sum=d[re[l]];
return ;
}
int mid=(l+r)>>;
build(f[g].lc,l,mid);
build(f[g].rc,mid+,r);
push_up(g);
}
void add(int g,int l,int r,int k)
{
if(f[g].l>=l && f[g].r<=r)
f[g].sum+=gel(g)*k,f[g].delay+=k;
else
{
int mid=(f[g].l+f[g].r)/;
if(r<=mid) add(f[g].lc,l,r,k);
else if(l>mid) add(f[g].rc,l,r,k);
else add(f[g].lc,l,mid,k),add(f[g].rc,mid+,r,k);
push_up(g);
}
}
long long get(int g,int l,int r)
{
if(f[g].l>=l && f[g].r<=r)
return f[g].sum;
else
{
push_down(g);
int mid=(f[g].l+f[g].r)/;
if(r<=mid) return get(f[g].lc,l,r);
else if(l>mid) return get(f[g].rc,l,r);
else return get(f[g].lc,l,mid)+get(f[g].rc,mid+,r);
}
}
long long Get(int x)
{
long long sum=;
while(x!=)
{
sum+=get(rt,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
return sum;
}
//操作 1 :把某个节点 x 的点权增加 a 。
//操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
//操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&d[i]);
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
link[u].push_back(v);
link[v].push_back(u);
}
dfs1(,);
top[]=,dfs2(,);
build(rt,,tot);
while(m--)
{
scanf("%d%d",&opt,&x);
if(opt==) printf("%lld\n",Get(x));
else
{
scanf("%lld",&a);
if(a!=)
{
if(opt==) add(rt,dfn[x],dfn[x],a);
else if(opt==) add(rt,dfn[x],dfn[x]+si[x]-,a);
}
}
}
return ;
}
[HAOI2015]树上操作(树链剖分)的更多相关文章
- bzoj4034[HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6163 Solved: 2025[Submit][Stat ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...
- BZOJ4034 [HAOI2015]树上操作 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...
- P3178 [HAOI2015]树上操作 树链剖分
这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇. 题干: 题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权.然后有 M 个操作, ...
- BZOJ4034[HAOI2015]树上操作——树链剖分+线段树
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- BZOJ 4034[HAOI2015]树上操作(树链剖分)
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...
- bzoj4034 [HAOI2015]树上操作——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034 树剖裸题: 一定要注意 long long !!! update 的时候别忘了 pus ...
- [HAOI2015]树上操作-树链剖分
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; #define mid ((l+r)>> ...
随机推荐
- MySQL性能优化:MySQL中的隐式转换造成的索引失效
数据库优化是一个任重而道远的任务,想要做优化必须深入理解数据库的各种特性.在开发过程中我们经常会遇到一些原因很简单但造成的后果却很严重的疑难杂症,这类问题往往还不容易定位,排查费时费力最后发现是一个很 ...
- 如何看Crash 文件
如何查看崩溃日志 好了,获得是人类可读语言的崩溃日志后,或者是从别人手机到处崩溃日志后,下一步就是查看了.下面就正对一个程序猿该如何看稍微说说. 崩溃日志头 1 2 3 4 5 6 7 8 9 ...
- springMvc web项目中restful风格的api路径中有小数点会被过滤后台拿不到最后一个小数点的问题
有两种解决方案: 1:在api路径中加入:.+ @RequestMapping("/findByIp/{ip:.+}") public Object test(@PathVaria ...
- 开发板免费领!腾讯云IoT应用创新大赛正式启动!
大赛简介 腾讯云IoT应用创新大赛是腾讯云面向物联网领域举办的大型竞赛,通过腾讯云IoT全链路产品能力,开放平台和服务,与广大开发者共同创新,孵化优秀的IoT产品和解决方案,共同构建IoT应用生态. ...
- windows10 powershell上切换至cmd
前言 在windows10 上是遇到了坑,因为出现了这样的情况!不要说什么盗版,公司买的正版呢. 上图是powershell,下图是 cmd,然后我同样使用powershell 与 cmd,查询nod ...
- jenkins安装自动部署
1.1简介: 开源项目,一个可扩展的持续集成引擎.提供了一种易于使用的持续集成系统,能实施监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图表的形式形象地展示项目构建的趋势和稳定性.还做到持 ...
- 3.24 7.13 Python基础汇总
对象类型 类型名称 示例 简要说明 备注 数字 int,float,complex 1234,3.14,1.3e5,3+4j 数字大小没有限制 十六进制用0x前缀和0-9,a-f表示 字符串 str ...
- JVM探秘:四种引用、对象的生存与死亡
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. Java虚拟机的内存区域中,程序计数器.Java栈和本地方法栈是线程私有的,随线程而生 ...
- GraphicsLab Project之Diffuse Irradiance Environment Map
作者:i_dovelemon 日期:2020-01-04 主题:Rendering Equation,Irradiance Environment Map,Spherical Harmonic 引言 ...
- 「UVA12004」 Bubble Sort 解题报告
UVA12004 Bubble Sort Check the following code which counts the number of swaps of bubble sort. int f ...