【线段树】bzoj1756 Vijos1083 小白逛公园
我们知道,求一段序列的最大子段和是O(n)的,但是这样是显然会超时的。
我们需要一个数据结构来支持修改和计算的操作,对于这种修改一个而查询区间的问题,考虑使用线段树。
在线段树中,除了左端点,右端点,左儿子指针,右儿子指针之外,新开4个域——max,maxl,maxr,sum,其中sum为该区间的和,max为该区间上的最大子段和,maxl为必须包含左端点的最大子段和,maxr为必须包含右端点的最大子段和。
然后就……可以用线段树来统计了,注意求得的最大子段和中至少包含1个元素,所以出现了样例那样的输出负值。
修改时:
1、若左儿子的maxr和右儿子的maxl都为负,就从中取较大的为该节点的max(防止一个都不取),反之取二者中正的(都正就都取)。
2、将该节点的max用左右儿子的max更新。
3、该节点的maxl为左儿子的maxl与左儿子sum和右儿子maxl和的最大值。
4、该节点的maxr为右儿子的maxr与右儿子sum和左儿子maxr和的最大值。
5、该节点的sum为左右儿子的sum和。
查询时:
1、如果查询区间覆盖这一节点,将该节点信息返回。
2、如果只与一个儿子有交集,就返回在那个儿子中查找到的信息。
3、如果与两个儿子都有交集,就先分别计算出两个儿子的信息,然后按修改的方式将两个信息合并,然后返回。
4、最后返回的max值即为答案。
——http://www.cnblogs.com/whitecloth/archive/2012/03/22/2410925.html
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 500001
struct Node{int maxv,maxl,maxr,sumv;}T[N<<2];
inline void pushup(Node &rt,const Node &ls,const Node &rs)
{
if(ls.maxr<0 && rs.maxl<0)
rt.maxv=max(ls.maxr,rs.maxl);
else
{
rt.maxv=0;
if(ls.maxr>0)
rt.maxv+=ls.maxr;
if(rs.maxl>0)
rt.maxv+=rs.maxl;
}
rt.maxv=max(rt.maxv,ls.maxv);
rt.maxv=max(rt.maxv,rs.maxv);
rt.maxl=max(ls.maxl,ls.sumv+rs.maxl);
rt.maxr=max(rs.maxr,rs.sumv+ls.maxr);
rt.sumv=ls.sumv+rs.sumv;
}
void buildtree(int rt,int l,int r)
{
if(l==r)
{
scanf("%d",&T[rt].maxv);
T[rt].sumv=T[rt].maxl=T[rt].maxr=T[rt].maxv;
return;
}
int m=(l+r>>1);
buildtree(rt<<1,l,m);
buildtree(rt<<1|1,m+1,r);
pushup(T[rt],T[rt<<1],T[rt<<1|1]);
}
void update(int p,int v,int rt,int l,int r)
{
if(l==r)
{
T[rt].sumv=T[rt].maxl=T[rt].maxr=T[rt].maxv=v;
return;
}
int m=(l+r>>1);
if(p<=m) update(p,v,rt<<1,l,m);
else update(p,v,rt<<1|1,m+1,r);
pushup(T[rt],T[rt<<1],T[rt<<1|1]);
}
Node query(int ql,int qr,int rt,int l,int r)
{
if(ql<=l&&r<=qr) return T[rt];
int m=(l+r>>1);
if(ql<=m && m<qr)
{
Node res;
pushup(res,query(ql,qr,rt<<1,l,m),query(ql,qr,rt<<1|1,m+1,r));
return res;
}
else if(ql<=m) return query(ql,qr,rt<<1,l,m);
else return query(ql,qr,rt<<1|1,m+1,r);
}
int n,m;
int main()
{
int op,x,y;
scanf("%d%d",&n,&m);
buildtree(1,1,n);
for(;m;--m)
{
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
if(x>y)
swap(x,y);
printf("%d\n",query(x,y,1,1,n).maxv);
}
else update(x,y,1,1,n);
}
return 0;
}
【线段树】bzoj1756 Vijos1083 小白逛公园的更多相关文章
- 线段树 || BZOJ1756: Vijos1083 小白逛公园 || P4513 小白逛公园
题面:小白逛公园 题解: 对于线段树的每个节点除了普通线段树该维护的东西以外,额外维护lsum(与左端点相连的最大连续区间和).rsum(同理)和sum……就行了 代码: #include<cs ...
- bzoj1756 Vijos1083 小白逛公园
Description 小新经常陪小白去公园玩,也就是所谓的遛狗啦-在小新家附近有一条"公园路",路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. ...
- Bzoj 1756: Vijos1083 小白逛公园 线段树
1756: Vijos1083 小白逛公园 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1021 Solved: 326[Submit][Statu ...
- BZOJ 1756: Vijos1083 小白逛公园
题目 1756: Vijos1083 小白逛公园 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 856 Solved: 264[Submit][Sta ...
- 【Vijos1083/BZOJ1756】小白逛公园(线段树)
[写在前面]TYC (Little White) 真是太巨啦! 题目: Vijos1083 分析: 一眼看上去就是线段树啊-- 然而当我这种蒟蒻兴高采烈地把线段树模板敲了一半,却发现一个问题: 这子区 ...
- 【BZOJ】1756: Vijos1083 小白逛公园(线段树)
题目 传送门:QWQ 分析 线段树维护一下最大子序列 维护一下最大前缀 最大后缀 区间和 就ok了 好像只能用结构体..... 代码 #include <bits/stdc++.h> u ...
- [日常摸鱼]Vijos1083小白逛公园-线段树
题意:单点修改,询问区间最大子段和,$n\leq 5e5$ 考虑分治的方法$O(nlogn)$求一次最大子段和的做法,我们是根据中点分成左右两个区间,那么整个区间的答案要么是左边答案,要么是右边答案, ...
- 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)
P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...
- vijos1083:小白逛公园
小白逛公园 描述 小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. 一开始,小白就根据公园的 ...
随机推荐
- Minecraft 插件 world edit 的cs 命令
现在 jar包 http://www.mozilla.org/rhino ,放到classpath 我是放到libs目录中, 1.8 spi 服 @ECHO OFFjava -cp ".;. ...
- vim 标记 mark 详解 (转载)
http://www.cnblogs.com/jianyungsun/archive/2011/02/14/1954057.html Vim 允许你在文本中放置自定义的标记.命令 "ma&q ...
- ubuntu源码安装node7+
在官网上下载了node的tar.xz文件(node7.3.0),安装分为两步:1.解压 2.安装 解压也分成两步,首先用xz -d xxx.tar.xz解压为xxx.tar,然后用tar -xvf ...
- spring mvc 第二天【注解实现springmvc Handler处理ajax简单请求 的配置】
这里使用的是在前台发起ajax请求Handler,后台伪造数据响应给前台, 配置对应ajax请求的Handler信息如下 @Controller public class MyController { ...
- NTKO控件在阅读PDF时,显示DEMO的问题
NTKO控件在阅读PDF时,显示DEMO的问题, 原因是加载了以前的DEMO版本的控件.解决办法是: 在命令行中执行命令: regsvr32 /u NtkoOleDocAll.DLL 卸载老版本的控件 ...
- Endless Sky源码学习笔记-4
事件处理: 事件包括:debug模式切换.切换到登陆窗口.退出.窗口大小变化.全屏切换和游戏中的鼠标键盘输入.处理方式分为两类,前几个为简单的if处理,最后一个涉及到游戏中的控制和交互,且事件由每一个 ...
- python tm_isdst = -1, 0, 1 datetime module
Python 里的tm_isdst DST 是daylight saving time, 意思是:夏令时 在python的time, datetime模块下,按照struct_time格式输出时间,最 ...
- funny_python 01 import antigravity
在Python里面import antigravity 会发现另一个小彩蛋 Tada~ 其实就是打开了xkcd的一个python主题漫画 鼠标停留在图片上,还会看到标题: "I wrote ...
- Redis学习笔记-进阶
Redis持久化方案 redis有rdb和aof两种持久化方案 1)rdb方式 当符合一定条件时会自动将内存中的所有数据执行快照操作并存储到硬盘上 默认存储在redis根目录的dump.rdb文件中, ...
- 修改tomcat的端口