「HAOI2015」「LuoguP3178」树上操作(树链剖分
题目描述
有一棵点数为 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 ) 。
输出格式:
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
输入输出样例
说明
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
题解
先剖一下。
操作1:在dfn[x]处+=a
操作2:从dfn[x]到dfn[x]+siz[x]-1上区间+a
操作3:往上跳的同时ans+=find(dfn[top[x]],dfn[x])
几乎是阉割版的树剖了。
/*
qwerta
P3178 [HAOI2015]树上操作
Accepted
100
代码 C++,2.93KB
提交时间 2018-09-11 17:00:43
耗时/内存
993ms, 24476KB
*/
#include<cstdio>
#include<iostream>
using namespace std;
#define LL long long
const LL MAXN=+;
LL val[MAXN];
struct emm{
LL e,f;
}b[*MAXN];
LL h[MAXN];
LL tot=;
void con(LL x,LL y)
{
b[++tot].f=h[x];
h[x]=tot;
b[tot].e=y;
b[++tot].f=h[y];
h[y]=tot;
b[tot].e=x;
return;
}
LL d[MAXN],siz[MAXN],z[MAXN],fa[MAXN],top[MAXN];
void dfs(LL x)
{
siz[x]=,top[x]=x;
LL mac=,macc=-;
for(LL i=h[x];i;i=b[i].f)
if(!d[b[i].e])
{
d[b[i].e]=d[x]+;
fa[b[i].e]=x;
dfs(b[i].e);
siz[x]+=siz[b[i].e];
if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
}
z[x]=mac;
top[mac]=x;
return;
}
LL q[MAXN],dfn[MAXN];
void dfss(LL x)
{
q[++tot]=x;
dfn[x]=tot;
if(z[x])dfss(z[x]);
for(LL i=h[x];i;i=b[i].f)
if(fa[b[i].e]==x&&b[i].e!=z[x])
dfss(b[i].e);
return;
}
LL fitop(LL x)
{
if(top[x]==x)return x;
return top[x]=fitop(top[x]);
}
struct ahh{
LL l,r,mid;
long long v,laz;
}a[*MAXN];
#define lz (i<<1)
#define rz ((i<<1)|1)
#define amid a[i].mid
void build(LL i,LL ll,LL rr)
{
a[i].l=ll;
a[i].r=rr;
if(ll==rr){a[i].v=val[q[ll]];return;}
amid=(ll+rr)>>;
build(lz,ll,amid);
build(rz,amid+,rr);
a[i].v=a[lz].v+a[rz].v;
return;
}
void add(LL i,LL ll,LL rr,LL k)
{
if(a[i].l==ll&&a[i].r==rr){a[i].laz+=k;return;}
a[i].v+=(rr-ll+)*k;
if(rr<=amid)add(lz,ll,rr,k);
else if(amid+<=ll)add(rz,ll,rr,k);
else {add(lz,ll,amid,k);add(rz,amid+,rr,k);}
return;
}
long long ans=;
void pushtag(LL i)
{
if(!a[i].laz)return;
a[i].v+=(a[i].r-a[i].l+)*a[i].laz;
if(a[i].l==a[i].r){a[i].laz=;return;}
a[lz].laz+=a[i].laz;
a[rz].laz+=a[i].laz;
a[i].laz=;
return;
}
void find(LL i,LL ll,LL rr)
{
pushtag(i);
if(a[i].l==ll&&a[i].r==rr){ans+=a[i].v;return;}
if(rr<=amid)find(lz,ll,rr);
else if(amid+<=ll)find(rz,ll,rr);
else {find(lz,ll,amid);find(rz,amid+,rr);}
return;
}
LL s;
int main()
{
//freopen("a.in","r",stdin);
LL n,m;
scanf("%lld%lld",&n,&m);
for(LL i=;i<=n;++i)
scanf("%lld",&val[i]);
for(LL i=;i<n;++i)
{
LL u,v;
scanf("%lld%lld",&u,&v);
con(u,v);
}
s=;
d[s]=;
dfs(s);
tot=;
dfss(s);
for(LL i=;i<=n;++i)
top[i]=fitop(i);
build(,,n);
for(LL i=;i<=m;++i)
{
LL opt;
scanf("%lld",&opt);
if(opt==)
{
LL x,v;
scanf("%lld%lld",&x,&v);
add(,dfn[x],dfn[x],v);
}
else if(opt==)
{
LL x,v;
scanf("%lld%lld",&x,&v);
add(,dfn[x],dfn[x]+siz[x]-,v);
}
else
{
LL x;
scanf("%lld",&x);
ans=;
while(x)
{
find(,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
printf("%lld\n",ans);
}
}
return ;
}
「HAOI2015」「LuoguP3178」树上操作(树链剖分的更多相关文章
- 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]树上操作 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...
- bzoj4034 树上操作 树链剖分+线段树
题目传送门 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有 ...
- 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...
- P3178 [HAOI2015]树上操作 树链剖分
这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇. 题干: 题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权.然后有 M 个操作, ...
- cogs 1963. [HAOI 2015] 树上操作 树链剖分+线段树
1963. [HAOI 2015] 树上操作 ★★★☆ 输入文件:haoi2015_t2.in 输出文件:haoi2015_t2.out 简单对比时间限制:1 s 内存限制:256 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 为根的子树中所有点 ...
随机推荐
- SGU 分类
http://acm.sgu.ru/problemset.php?contest=0&volume=1 101 Domino 欧拉路 102 Coprime 枚举/数学方法 103 Traff ...
- What should do in Production
Using Compose in production https://docs.docker.com/compose/production/
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...
- 《流畅的Python》一副扑克牌中的难点
1.现在在看<流畅的Python>这本书,看了三页就发现,这本书果然不是让新手来入门的,一些很常见的知识点能被这个作者玩出花来, 唉,我就在想,下面要分析的这些的代码,就算我费劲巴拉的看懂 ...
- JS那些事儿——Gulp的入门使用
前言 新人使用gulp的一个记录. 首先对于第一个新事物,我会问gulp这是什么? 答:gulp是一个自动化构建工具,它可以做一些自动化的任务,比如: 检查Javascript 编译Sass(或Les ...
- android 计时器
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- Go -- 并发编程的两种限速方法
引子 golang提供了goroutine快速实现并发编程,在实际环境中,如果goroutine中的代码要消耗大量资源时(CPU.内存.带宽等),我们就需要对程序限速,以防止goroutine将资源耗 ...
- pycharm整体缩进的快捷键
选中多行,按tab进行缩进,按tab+shift去除缩进
- kafka-0.8.1.1总结
文件夹 一. 基础篇 1. 开篇说明 2. 概念说明 3. 配置说明 4. znode分类 5. kafka协议分类 6. Kafka线 ...
- ALERT日志中常见监听相关报错之三:ORA-609 TNS-12537 and TNS-12547 or TNS-12170 TNS-12535错误的排查
1.11G中ALERT日志中有报错ORA-609 TNS-12537 and TNS-12547 or TNS-12170 12170, 'TNS-12535等问题的解决方法: Troublesho ...