题目描述

有一棵点数为 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. 用CSS3变形创建半圆形导航

    http://www.xuanfengge.com/create-a-semicircle-with-css3-variant-navigation.html demo:http://tympanus ...

  2. Delphi使用进行post数据时超时设置

    因项目需要进行http的post提交数据,开始时用indy的idHttp组件,但是测试时发现当网络中断(如拔掉网线),idHttp的超时设置无效果,要等20秒才提示超时(参考网上的做法,将indy9升 ...

  3. python判断一个字符串是否是小数

    最近在写代码的时候,发现一个问题,想判断一个字符串是不是一个合法的小数,发现字符串没有内置判断小数的方法,然后就写了一个判断字符串是否是小数,可以判断正负小数,代码如下:   1 2 3 4 5 6 ...

  4. MACBOOK 忘记密码

    如果没有系统安装盘,可以采用下面的几种方法:首先,启动机器,启动时按住Apple和S键,以单用户模式(single user mode)进入系统.输入:mount -uv / 然后回车.接下来可以采用 ...

  5. Java中Class.this和this的区别(转)

    当inner class(内部类)必顺使用到outer class(外部类)的this instance(实例)时,或者匿名内部类要使用外部类的实例. 例: class Outer{ String d ...

  6. MD5进行文件完整性校验的操作方法

    我组产品包含大量音频和图片资源,MD5主要就用来检测这些资源文件的完整性.主要思路是:先计算出所有资源文件的MD5值,存到一个xml文件中,作为标准的MD5值.然后把这个xml文件放到我们的产品中,每 ...

  7. 使用crontab定时执行脚本时别忘了输出重定向>

    原文:https://blog.csdn.net/solmyr_biti/article/details/50683279 -------------------------------------- ...

  8. 【转】Code Your Own PHP MVC Framework in 1 Hour

      原文: https://www.codeproject.com/Articles/1080626/Code-Your-Own-PHP-MVC-Framework-in-Hour --------- ...

  9. 生活娱乐 ATM机键盘余温泄露密码

    安全系统存漏洞 ATM机键盘余温或泄露密码 ATM机会泄露你的银行卡密码? 据美国<大众科学>网站8月30日报道,你的手指在ATM机上留下的余温能让尾随你而来的黑客准确获知你的密码. 加利 ...

  10. invlpg 指令简单介绍

    invlpg 指令简单介绍 void tlb_invalidate(pde_t *pgdir, void *va) { // Flush the entry only if we're modifyi ...