我们知道,求一段序列的最大子段和是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 小白逛公园的更多相关文章

  1. 线段树 || BZOJ1756: Vijos1083 小白逛公园 || P4513 小白逛公园

    题面:小白逛公园 题解: 对于线段树的每个节点除了普通线段树该维护的东西以外,额外维护lsum(与左端点相连的最大连续区间和).rsum(同理)和sum……就行了 代码: #include<cs ...

  2. bzoj1756 Vijos1083 小白逛公园

    Description 小新经常陪小白去公园玩,也就是所谓的遛狗啦-在小新家附近有一条"公园路",路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. ...

  3. Bzoj 1756: Vijos1083 小白逛公园 线段树

    1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1021  Solved: 326[Submit][Statu ...

  4. BZOJ 1756: Vijos1083 小白逛公园

    题目 1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 856  Solved: 264[Submit][Sta ...

  5. 【Vijos1083/BZOJ1756】小白逛公园(线段树)

    [写在前面]TYC (Little White) 真是太巨啦! 题目: Vijos1083 分析: 一眼看上去就是线段树啊-- 然而当我这种蒟蒻兴高采烈地把线段树模板敲了一半,却发现一个问题: 这子区 ...

  6. 【BZOJ】1756: Vijos1083 小白逛公园(线段树)

    题目 传送门:QWQ 分析 线段树维护一下最大子序列 维护一下最大前缀 最大后缀  区间和 就ok了 好像只能用结构体..... 代码 #include <bits/stdc++.h> u ...

  7. [日常摸鱼]Vijos1083小白逛公园-线段树

    题意:单点修改,询问区间最大子段和,$n\leq 5e5$ 考虑分治的方法$O(nlogn)$求一次最大子段和的做法,我们是根据中点分成左右两个区间,那么整个区间的答案要么是左边答案,要么是右边答案, ...

  8. 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)

    P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...

  9. vijos1083:小白逛公园

    小白逛公园 描述 小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. 一开始,小白就根据公园的 ...

随机推荐

  1. U盘安装WIN10专业版

    安装环境1个SSD,2个SATA盘. 安装时把2个SATA盘拔掉,并使SSD在BISO中的地位为0区的MASTER,否则安装时会出现,无法创建当前分区,和新建当前分区. 步骤:下载win10正式专业版 ...

  2. Linked List Start!

    (1)Delete Node in a Linked List 题意简单明了,用后一个节点来替换要删除的节点即可.代码如下: /** * Definition for singly-linked li ...

  3. 关于sizeof 跟strlen 的区别

    char *t = "我a"; char t1[MAX_PATH] = "aaaaaa"; char display1[MAX_PATH]; char disp ...

  4. asp.net LINQ LinqDataSource控件显示数据和DropdownList显示数据

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  5. [python] python实现2048游戏,及代码解析。

    我初学python,有不对之处望大家指教.转载请征得同意. 我在网络上也找了一些2048游戏代码的讲解,但都不是特别详细.所以我希望能够尽量详细的讲解.同时,有的地方我也不懂,希望大家能帮助补充.我会 ...

  6. Js文件中文乱码

    aspx页面引用的js文件中如果包括中文,中文显示乱码或者引起脚本错误.提示是'未结束的字符串' 原因:aspx页面的默认编码是utf-8,而js文件的默认编码是gb2312,两者之间不一致引起了中文 ...

  7. 在Android中使用Java 8的lambda表达式

    作为一名Java开发者,或许你时常因为缺乏闭包而产生许多的困扰.幸运的是:Java's 8th version introduced lambda functions给我们带来了好消息;然而,这咩有什 ...

  8. SwipeRefreshLayout嵌套ScrollView包裹复杂头布局和RecyclerView

    布局如下:上面是一个描述有:头像和部分信息的布局,底部是一个RecyclerView: 想法:想实现RecyclerView向上滚动的时候,隐藏上面的头像布局信息:使用了 CoordinatorLay ...

  9. ViewPager的简单使用

    1.布局文件 a.主布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xml ...

  10. div水平垂直居中

    我们平时常用的定高,top:50%:left:50%和margin-left负一半宽度margin-top负一半高度的居中方式暂不考虑,因为这种方式大家都会. 第一种绝对定位(absolute cen ...