「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 为根的子树中所有点 ...
随机推荐
- hdu4848 求到达每个点总时间最短(sum[d[i]])。
开始的时候是暴力dfs+剪枝,怎么也不行.后来参考他人思想: 先求出每个点之间的最短路(这样预处理之后的搜索就可以判重返回了),截肢还是关键:1最优性剪枝(尽量最优:目前的状态+预计还有的最小时间&g ...
- 激活win10系统的方法(亲测)
WIN+X 按A (或者点击左下角有个windows小图标“鼠标右键”选择选择“命令提示符号(管理员)”) 输入下面命令,回车(一行按一个回车键)slmgr.vbs /upkslmgr /ipk W2 ...
- python--输出自己需要的字符串连接的的方式
python中有很多字符串连接方式,今天在写代码,顺便总结一下,从最原始的字符串连接方式到字符串列表连接,大家感受下: 最原始的字符串连接方式:str1 + str2 python 新字符串连接语法: ...
- (45)C#网络3 socket
一.TCP传输 using System.Net.Sockets; 1.最基本客户端连服务器 服务端运行后一直处于监听状态,客户端每启动一次服务端就接收一次连接并打印客户端的ip地址和端口号.(服务端 ...
- dropwizard问题记录1:如何进行mvn package打包,如何在项目目录下运行
dropwizard的helloworld入门教程,跟着教程一步步写很容易,但是最后打包时暴露了自己底子太差的缺陷 mvn package操作 之前工作中完全没有接触过这种打包方式,都是直接打war包 ...
- 《深入理解mybatis原理》 MyBatis的二级缓存的设计原理
MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能.本文将全面分析MyBatis的二级缓存的设计原理. 如上图所示,当开一个会话时,一个SqlS ...
- Jquery表单序列化和json操作
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- maven删除不必要的依赖;优化pom依赖研究
mvn dependency:copy-dependencies -DoutputDirectory=/home/admin/git/oceanus/test 会把所有依赖的插件版本都拷贝进去,而不是 ...
- 浅谈JavaScript的事件(事件对象)
在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含这所有与事件有关的信息.包括导致事件的元素.事件的类型和事件的相关信息.例如鼠标操作的事件中,会包含鼠标的位置信息.而键盘触发的 ...
- HDU 6068 Classic Quotation KMP+DP
Classic Quotation Problem Description When online chatting, we can save what somebody said to form h ...