[HAOI2015]树上操作(树链剖分,线段树)
题目描述
有一棵点数为 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]树上操作(树链剖分,线段树)的更多相关文章
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- B20J_3231_[SDOI2014]旅行_树链剖分+线段树
B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- fzu 2082 过路费 (树链剖分+线段树 边权)
Problem 2082 过路费 Accept: 887 Submit: 2881Time Limit: 1000 mSec Memory Limit : 32768 KB Proble ...
随机推荐
- LeetCode 531----Lonely Pixel I----两种算法之间性能的比较
Lonely Pixel I 两种算法之间的性能比较 今天参加LeetCode Weekly Contest 22,第二题 "Lonely Pixel I" 问题描述如下: Giv ...
- Android解析WindowManagerService(三)Window的删除过程
前言 在本系列文章中,我提到过:Window的操作分为两大部分,一部分是WindowManager处理部分,另一部分是WMS处理部分,Window的删除过程也不例外,本篇文章会介绍Window的删除过 ...
- json 对象里面含有 =的解决办法
今天通过restful 调用接口的时候,遇到这样的问题,通过接口返回的数据如下: { "code": 0, "message": "成功", ...
- JDK自带工具native2ascii
背景:在做Java开发的时候,常常会出现一些乱码,或者无法正确识别或读取的文件,比如常见的validator验证用的消息资源(properties)文件就需要进行Unicode重新编码.原因是java ...
- 《IT老外在中国》第11期:首次访华的编程巨匠、C#之父Anders
见到Anders的时候,他正专注的倾听国内开发者的提问,一副远视眼镜斜歪着架在头顶,宽松的深蓝色休闲毛衫随意套在白色圆领T恤外. 如果不是他那专注的神情,以及现场见证开发者对他的狂热崇拜,很难想象这位 ...
- 数据库常用SQL用法
查找某列数据包含某一字符串: SELECT * FROM table WHERE column LIKE '%string%' 查找某列数据以某些字符串开头: SELECT * FROM table ...
- Java学习---JAVA的类设计
基础知识 JAVA是由C/C++语言发展而来的纯面向对象语言,其基本元素包括:简单数据类型 和 复合数据类型(即类).类是对客观事物的抽象描述,它有面向对象的四个特点,即:封装性.继承性.多态性和通信 ...
- Skype for Business 安装组件RewriteModule失败
最近QQ网友提到部署Skype for Business,安装组件时提示安装必备组件失败:RewriteModule,如下图,安装文件名是rewrite_2.0_rtw_x64.msi,尝试手动安装也 ...
- Linux中脚本的使用方法
Linux中脚本的使用方法 一.前言 关于Linux中的脚本的用法,一直没有时间去好好地总结,正好今天下雨,就好好的整理一下思路吧,其实精通了一门语言,比如C语言,学习其他语言需要的成本是非常少的,同 ...
- SQL监控:mysql及mssql数据库SQL执行过程监控审计
转载 Seay_法师 最近生活有很大的一个变动,所以博客也搁置了很长一段时间没写,好像写博客已经成了习惯,搁置一段时间就有那么点危机感,心里总觉得不自在.所以从今天起还是要继续拾起墨笔(键盘),继续好 ...