题目描述

有一棵点数为 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 ) 。

输出格式:

对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

输入输出样例

输入样例#1:
复制

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
输出样例#1: 复制

6
9
13

说明

对于 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」树上操作(树链剖分的更多相关文章

  1. bzoj4034[HAOI2015]树上操作 树链剖分+线段树

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 6163  Solved: 2025[Submit][Stat ...

  2. bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Stat ...

  3. BZOJ4034 [HAOI2015]树上操作 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...

  4. bzoj4034 树上操作 树链剖分+线段树

    题目传送门 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有 ...

  5. 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树

    [BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...

  6. P3178 [HAOI2015]树上操作 树链剖分

    这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇. 题干: 题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权.然后有 M 个操作, ...

  7. cogs 1963. [HAOI 2015] 树上操作 树链剖分+线段树

    1963. [HAOI 2015] 树上操作 ★★★☆   输入文件:haoi2015_t2.in   输出文件:haoi2015_t2.out   简单对比时间限制:1 s   内存限制:256 M ...

  8. BZOJ4034[HAOI2015]树上操作——树链剖分+线段树

    题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...

  9. bzoj 4034: [HAOI2015]树上操作——树链剖分

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...

  10. BZOJ 4034[HAOI2015]树上操作(树链剖分)

    Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...

随机推荐

  1. ngxtop

    http://www.cnblogs.com/felixzh/p/8709201.html

  2. ZOJ 1112 Dynamic Rankings【动态区间第K大,整体二分】

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112 题意: 求动态区间第K大. 分析: 把修改操作看成删除与增加 ...

  3. 死磕 java同步系列之自己动手写一个锁Lock

    问题 (1)自己动手写一个锁需要哪些知识? (2)自己动手写一个锁到底有多简单? (3)自己能不能写出来一个完美的锁? 简介 本篇文章的目标一是自己动手写一个锁,这个锁的功能很简单,能进行正常的加锁. ...

  4. VC++下编译Libgeotiff(含Libtiff)

    转自原文Win10+VC++下编译Libgeotiff(含Libtiff)详细图文教程 GeoTiff是包含地理信息的一种Tiff格式的文件.Libgeotiff就是一个操作GeoTiff文件的库.同 ...

  5. ceph工作原理和安装

    一.概述 Ceph是一个分布式存储系统,诞生于2004年,最早致力于开发下一代高性能分布式文件系统的项目.随着云计算的发展,ceph乘上了OpenStack的春风,进而成为了开源社区受关注较高的项目之 ...

  6. UML类间关系

    1继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系:在Java中此类关系通过关键字exten ...

  7. centos或者ubuntu设置ssh免密码登陆

    1. 输入  # ssh-keygen -t rsa -P ""  然后一路回车 2.输入  # cat ~/.ssh/id_rsa.pub >> ~/.ssh/aut ...

  8. addEventListener event

    addEventListener   先看个例子: document.getElementById("myBtn").addEventListener("click&qu ...

  9. Ubuntu安装教程--Win7系统中含100M保留分区

    1.检查 Win7 保留分区 1)进入 Win7 打开库目录.在左側栏找到"计算机",瞄准点右键选择"管理"菜单: 2)在出来的管理面板左边找到"磁盘 ...

  10. Qt Quick之StackView具体解释(1)

    Qt Quick中有个StackView.我在<Qt Quick核心编程>一书中没有讲到.近期有人问起,趁机学习了一下,把它的基本使用方法记录下来. 我准备分两次来讲.第一次讲主要的使用方 ...