题目描述

有一棵点数为 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. BOJ 2773 第K个与m互质的数

    算法是关键,得出1-m内的互质数,然后类推计算即可.下面有详细说明. #include<iostream> #include<cstring> using namespace ...

  2. LeetCode OJ--Reverse Linked List II

    http://oj.leetcode.com/problems/reverse-linked-list-ii/ 链表的操作 #include <iostream> using namesp ...

  3. 转:Linux字符编码方式

    首先,解释一下字符集: 汉字编码: * GB2312字集是简体字集,全称为GB2312(80)字集,共包括国标简体汉字6763个. * BIG5字集是台湾繁体字集,共包括国标繁体汉字13053个. * ...

  4. Win10 - 默认图片查看器恢复

    1. 新建一个文本文件“1.txt” 2. 在“1.txt”中添加如下代码,并保存: Windows Registry Editor Version 5.00 ; Change Extension's ...

  5. 【mac】mac上安装JDK

    安装步骤就是在Oracle官网下载你想要的JDK版本下载,下载的时候同意协议即可 这里就给出jdk安装的位置 还有一点要注意的是,在指定JVM的位置的时候,需要指定到home目录下

  6. C语言枚举类型(Enum)

    在实际编程中,有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程等. 以每周七天为例, ...

  7. JZ2440:时钟设置

    这一节的目标是对板子上的时钟有一个初步的了解.而且能通过初步设置.为我们接下来的程序做准备. 1. 板子上的基本资源: 板载晶振12M 主时钟源和 USB 时钟源都是晶振 2. 手冊中的相关项(按时钟 ...

  8. 标C编程笔记day04 预处理、宏定义、条件编译、makefile、结构体使用

    预处理:也就是包括须要的头文件,用#include<标准头文件>或#include "自己定义的头文件" 宏定义,如:#define PI 3.1415926 查看用宏 ...

  9. eclipse新建android项目出现非常多错误

    如图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSGFycnlXZWFzbGV5/font/5a6L5L2T/fontsize/400/fil ...

  10. Java 复杂excel报表导出

    MyExcel,是一个可直接使用Html文件,或者使用内置的Freemarker.Groovy.Beetl等模板引擎Excel构建器生成的Html文件,以Html文件中的Table作为Excel模板来 ...