洛谷 P3178 BZOJ 4034 [HAOI2015]树上操作
题目描述
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
输入输出格式
输入格式:
第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
输出格式:
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
输入输出样例
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
6
9
13
说明
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
吐槽
今晚真是填坑之夜呀!一连填了3个一个月以上的老坑!
这题和我上一篇博文说的悲惨程度差不多——

是的,你没有看错,还有[Next Page]这种东西……5月初我就开始做这题了……
人越急越写不出东西,所以遇到某些题卡住了,可以搁置一下,过段时间再来写,但是如果第二次冷静下来还是写错,那么就是脑子里的东西错了……
我观察洛谷给的错误情况,除了CE之类的,剩下的错误都是在50行以后,这说明我写的程序的持久性出了问题(不是可持久,是持久),一些维护修改的东西出错了。
树剖方面
两个dfs第一次调用之后就不再用它了,还有询问时opt3轻重链向上跳的过程,前50个询问都能处理的挺好,不太可能出问题。
就剩修改操作了,opt1和opt2两个函数里都只有一句话,反复检查没有问题我为什么一句话都要反复检查……,于是bug被限定到了线段树部分——
线段树方面
首先是建树,按照dfs序获取轻重链相连组成的序列是在树剖的dfs2部分实现的,获取序列a之后maketree只调用了一次,建出来的线段树毕竟也坚持了50个询问,基本排除出bug的可能。
然后是含有修改的一堆函数,极有可能出bug。询问函数query,表面上不修改线段树,但是其中有一个pushdown啊,可能出错;更新函数change,这个就直接是更改线段树啊!高危!最后是前面两者都调用了的pushdown,简简单单6行,好像没毛——不对,前天写维护序列这题的时候,它的双lazy和我预想的不太一样啊,嗯,极危!先从它查起!
大概确定了出bug范围,剩下的就好搞了,直接找原来写的模板对比。
(一段时间后)
”他丫的我半年前学的线段树lazy是假的,更重要的是我还用它A了不知道多少水题,越错越深,查错时完全忽略了这里……“
我就不把错误的pushdown放上来误导大家了。
非常兴奋地改了这里,迫不及待地交了上去,50分。我居然忘了加long long!为了省事。大家在我的代码开头可以看到一个神奇的define……
解题思路
就是裸的树剖,可以看洛谷的题解百科。
这题的询问比较方便跳链,于是我偷了个小懒,opt3没套模板,做了个小优化,省时省力。
源代码
#include<vector>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std; int n,m; struct Edge{
int next,to;
}e[];
int cnt=,head[]={};
void add(int u,int v)
{
e[cnt]={head[u],v};
head[u]=cnt++;
} struct Tree{
int w;
int fa;
vector<int> son;
int num_to;
int wson;
int top;
int id;
}t[];
long long a[]={};
int dfs1(int fa,int u)
{
t[u].fa=fa;
t[u].num_to=;
for(int i=head[u],maxn=-;i;i=e[i].next)
{
int v=e[i].to;
if(v==fa) continue;
t[u].son.push_back(v);
int temp=dfs1(u,v);
t[u].num_to+=temp;
if(temp>maxn)
{
maxn=temp;
t[u].wson=v;
}
}
return t[u].num_to;
}
int id=;
void dfs2(int top,int u)
{
t[u].top=top;
t[u].id=id;
a[id]=t[u].w;
int sz=t[u].son.size();
if(!sz)
return;
id++;
dfs2(top,t[u].wson);
for(int i=;i<sz;i++)
{
int v=t[u].son[i];
if(v==t[u].wson) continue;
id++;
dfs2(v,v);
}
} struct SegTree{
int l,r;
long long sum;
}s[];
long long lazy[]={};
void pushdown(int node)//这个pushdown是真的了
{
if(!lazy[node])return;
int lson=node<<,rson=node<<|;
s[lson].sum+=lazy[node]*(s[lson].r-s[lson].l+);
s[rson].sum+=lazy[node]*(s[rson].r-s[rson].l+);
lazy[lson]+=lazy[node];
lazy[rson]+=lazy[node];
lazy[node]=;
}
void maketree(int node,int l,int r)
{
if(l==r)
{
s[node]={l,r,a[l]};
return;
}
int mid=l+r>>;
maketree(node<<,l,mid);
maketree(node<<|,mid+,r);
s[node]={l,r,s[node<<].sum+s[node<<|].sum};
}
void change(int x,int l,int r,int k)
{
if(r<s[x].l||s[x].r<l)return;
if(l<=s[x].l&&s[x].r<=r)
{
s[x].sum+=k*(s[x].r-s[x].l+);
lazy[x]+=k;
return;
}
pushdown(x);
int lson=x<<,rson=x<<|;
change(lson,l,r,k);
change(rson,l,r,k);
s[x].sum=s[lson].sum+s[rson].sum;
}
long long query(int x,int l,int r)
{
if(r<s[x].l||s[x].r<l)return ;
if(l<=s[x].l&&s[x].r<=r)
{
return s[x].sum;
}
pushdown(x);
int lson=x<<,rson=x<<|;
return query(lson,l,r)+query(rson,l,r);
} inline void opt1(int x,int k)
{
change(,t[x].id,t[x].id,k);
}
inline void opt2(int x,int k)
{
change(,t[x].id,t[x].id+t[x].num_to-,k);
}
inline void opt3(int x)
{
long long ans=;
while(x)
{
ans+=query(,t[t[x].top].id,t[x].id);
x=t[t[x].top].fa;
}
printf("%lld\n",ans);
} main()
{
//freopen("test.in","r",stdin);
//freopen("haoi2015_t21.out","w",stdout);//在cogs提交的标记历历在目……
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++)
scanf("%lld",&t[i].w);
for(int i=,u,v;i<n;i++)
{
scanf("%lld%lld",&u,&v);
add(u,v);
add(v,u);
}
dfs1(,);
dfs2(,);
maketree(,,n);
for(int i=,mode,x,y;i<=m;i++)
{
scanf("%lld",&mode);
if(mode==)
{
scanf("%lld%lld",&x,&y);
opt1(x,y);
}
else if(mode==)
{
scanf("%lld%lld",&x,&y);
opt2(x,y);
}
else
{
scanf("%lld",&x);
opt3(x);
}
}
return ;
}
洛谷 P3178 BZOJ 4034 [HAOI2015]树上操作的更多相关文章
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6779 Solved: 2275[Submit][Stat ...
- [BZOJ]4034: [HAOI2015]树上操作
[HAOI2015]树上操作 传送门 题目大意:三个操作 1:a,b,c b节点权值+c 2:a,b,c 以b为根的子树节点权值全部+c 3:a,b 查询b到根路径的权值和. 题解:树链剖分 操作1 ...
- bzoj 4034 [HAOI2015]树上操作 入栈出栈序+线段树 / 树剖 维护到根距离和
题目大意 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...
- BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)
题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
- BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]
题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- BZOJ 4034[HAOI2015]树上操作(树链剖分)
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...
随机推荐
- 使用poi读取word2007(.docx)中的复杂表格
使用poi读取word2007(.docx)中的复杂表格 最近工作需要做一个读取word(.docx)中的表格,并以html形式输出.经过上网查询,使用了poi. 对于2007及之后的word文档,需 ...
- hdoj--5104--Primes Problem(素数打表)
Primes Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- Java 位运算符 &、|、^、~、<<、>>、>>>
撸了N久的代码,但是突然冒出来个位运算,我就蒙蔽了,这是什么?我是谁?我在干什么?我在哪? 1)闲扯 关于位运算符无非也就 与(&).或(|).异或(^).取反(~).左移(<< ...
- Centos6系列安装nginx
设置ssh服务为开机启动 输入命令:chkconfig sshd on 即可.注:若是chkconfig sshd off则禁止SSH开机启动 设定账号为bizuser ,密码为123456 第一步: ...
- windbg将调试信息保存到文本文件
在跟踪一些出现频率较低的问题时,有时候需要长时间调试,但是在在输出信息太多时可能前面的日志会被清空,为避免这种情况,可以将输出日志记录到文本文件以备查看. 1. 可以在启动时直接用带 -logo的命令 ...
- 详细解读css中的浮动以及清除浮动的方法
对于前端初学者来说,css浮动部分的知识是一块比较难以理解的部分,下面我将把我学习过程中的心得分享给大家. 导读: 1.css块级元素讲解 2.css中浮动是如何产生的 3.出现浮动后,如何清除浮 ...
- 全局设置border-box
全局设置 border-box 很好,更符合我们通常对一个「盒子」尺寸的认知.,其次它可以省去一次又一次的加加减减,它还有一个关键作用——让有边框的盒子正常使用百分比宽度.但是使用了 border-b ...
- buf.readInt32LE函数详解
offset {Number} 0 noAssert {Boolean} 默认:false 返回:{Number} 从该 Buffer 指定的带有特定尾数格式(readInt32BE() 返回一个较大 ...
- 一张图说明DIV盒子距离
虚线的宽高为你实际指定的width和height 虚线外的白色区域为padding 红色区域为border的width 红色外的区域为margin
- jQuery顺序加载图片(终版)
这一篇是对上一篇(jQuery顺序加载图片(初版)--http://www.cnblogs.com/newbie-cc/p/3707504.html)的改进. function loadImage(i ...