题目描述

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

输出格式:

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

思路:

树剖板子题,不解释了……

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<queue>
#include<algorithm>
#define int long long
#define rii register int i
#define rij register int j
using namespace std;
int n,m;
struct ljb{
int to,nxt;
}x[];
struct node{
int val,lazy;
}y[];
int f[],sd[],head[],val[],size[];
int weison[],cnt,bnt,nid[],nval[],ntop[];
int res;
void add(int from,int to)
{
cnt++;
x[cnt].to=to;
x[cnt].nxt=head[from];
head[from]=cnt;
}
void dfs1(int wz,int fa,int s)
{
sd[wz]=s;
f[wz]=fa;
size[wz]=;
int maxn=;
for(rii=head[wz];i!=;i=x[i].nxt)
{
int to=x[i].to;
if(to==fa)
{
continue;
}
dfs1(to,wz,s+);
size[wz]+=size[to];
if(size[to]>maxn)
{
maxn=size[to];
weison[wz]=to;
}
}
}
void dfs2(int wz,int top)
{
bnt++;
nid[wz]=bnt;
nval[bnt]=val[wz];
ntop[wz]=top;
if(weison[wz]==)
{
return;
}
dfs2(weison[wz],top);
for(rii=head[wz];i!=;i=x[i].nxt)
{
int to=x[i].to;
if(weison[wz]==to||f[wz]==to)
{
continue;
}
dfs2(to,to);
}
}
void build(int bh,int l,int r)
{
if(l==r)
{
y[bh].val=nval[l];
return;
}
int mid=(l+r)/;
build(bh*,l,mid);
build(bh*+,mid+,r);
y[bh].val+=y[bh*].val+y[bh*+].val;
}
void pushdown(int bh,int cd)
{
y[bh*].lazy+=y[bh].lazy;
y[bh*+].lazy+=y[bh].lazy;
y[bh*].val+=y[bh].lazy*(cd-(cd/));
y[bh*+].val+=y[bh].lazy*(cd/);
y[bh].lazy=;
}
void updata(int bh,int nl,int nr,int l,int r,int val)
{
int len=(nr-nl+);
if(l<=nl&&nr<=r)
{
y[bh].lazy+=val;
y[bh].val+=val*len;
return;
}
if(y[bh].lazy!=)
{
pushdown(bh,len);
}
int mid=(nl+nr)/;
if(l<=mid)
{
updata(bh*,nl,mid,l,r,val);
}
if(r>mid)
{
updata(bh*+,mid+,nr,l,r,val);
}
y[bh].val=(y[bh*].val+y[bh*+].val);
}
void query(int bh,int nl,int nr,int l,int r)
{
if(l<=nl&&r>=nr)
{
res+=y[bh].val;
return;
}
int mid=(nl+nr)/;
if(y[bh].lazy!=)
{
pushdown(bh,nr-nl+);
}
if(l<=mid)
{
query(bh*,nl,mid,l,r);
}
if(r>mid)
{
query(bh*+,mid+,nr,l,r);
}
}
int querylj(int from,int to)
{
int ans=;
while(ntop[from]!=ntop[to])
{
if(sd[ntop[from]]<sd[ntop[to]])
{
swap(from,to);
}
res=;
query(,,n,nid[ntop[from]],nid[from]);
ans+=res;
from=f[ntop[from]];
}
if(sd[from]>sd[to])
{
swap(from,to);
}
res=;
query(,,n,nid[from],nid[to]);
ans+=res;
return ans;
}
void addson(int wz,int val)
{
updata(,,n,nid[wz],nid[wz]+size[wz]-,val);
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(rii=;i<=n;i++)
{
scanf("%lld",&val[i]);
}
for(rii=;i<n;i++)
{
int from,to;
scanf("%lld%lld",&from,&to);
add(from,to);
add(to,from);
}
dfs1(,,);
dfs2(,);
build(,,n);
for(rii=;i<=m;i++)
{
int opt,from,to,val,kkk;
scanf("%lld",&opt);
if(opt==)
{
scanf("%lld%lld",&from,&val);
updata(,,n,nid[from],nid[from],val);
}
if(opt==)
{
scanf("%lld%lld",&from,&val);
addson(from,val);
}
if(opt==)
{
scanf("%lld",&from);
kkk=querylj(from,);
printf("%lld\n",kkk);
}
}
}

[HAOI2015]树上操作(树链剖分,线段树)的更多相关文章

  1. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  2. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  5. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  6. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  7. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  8. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

  9. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  10. fzu 2082 过路费 (树链剖分+线段树 边权)

    Problem 2082 过路费 Accept: 887    Submit: 2881Time Limit: 1000 mSec    Memory Limit : 32768 KB  Proble ...

随机推荐

  1. 文件路径太长无法删除 robocopy

    方法一:新建空文件夹 D:\temp robocopy D:\temp D:\target\source\test  /purge 或者在同一目录下,建一个空文件夹, test 在cmd下切换进入到当 ...

  2. Android实现图片下载并保存SD卡

    一.首先获取图片 //第一种获取图片的方法 String filePath = downloadUrl; //以下是取得图片的方法 取得的是InputStream,直接从InputStream生成bi ...

  3. Raspberry install wine

    sudo apt install wine winecfg出现问题 树莓派3B是卡片电脑,内存为1GB,一般运行Linux.Linux两种主流的内存分配方法2G/2G和3G/1G,树莓派系统后期优化性 ...

  4. winform基础控件总结

    转自:http://www.cnblogs.com/top5/archive/2010/04/29/1724039.html 基础 - 常用控件 C# WinForm开发系列 - CheckBox/B ...

  5. JDBC连接数据库反射实现O/R映射

    测试preparedStatement public void testPreparedStatement(){ Connection connection=null; PreparedStateme ...

  6. C# winfrom Datagridview表头样式和选中样式

    Griscolor是表格线的颜色 表头的样式修改如下图: 选中某一行的样色设置

  7. linux,强大的history命令

    如果你经常使用 Linux 命令行,那么使用 history(历史)命令可以有效地提升你的效率.本文将通过实例的方式向你介绍 history 命令的 15 个用法. 使用 HISTTIMEFORMAT ...

  8. oracle 大表 已有大数据量 建索引防卡 nologging

    create index idx_th_user_info_fans_name on th_user_info(fans_name) nologging;

  9. 深入探索C++对象模型(1) 关于对象(思维导图)

    通过上面整个关于对象的基础知识框架,我们来分析两个例子,看一下在内存中,对象究竟长什么样.   Demo1:C++对象模型的内存布局 class Point { public: Point( floa ...

  10. 枚举类型与位域枚举Enum

    一.概述 定义一个值类型,其中包含固定值集合.枚举类型变量可以是此集合中的任意一个或多个值.枚举使用enum关键字来声明,与类同级.枚举本身可以有修饰符,但枚举的成员始终是公共的,不能有访问修饰符.枚 ...