题目背景

小新经常陪小白去公园玩,也就是所谓的遛狗啦…

题目描述

在小新家附近有一条“公园路”,路的一边从南到北依次排着 nnn 个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。

一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第 aaa 个和第 bbb 个公园之间(包括 aaa 、 bbb 两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。

那么,就请你来帮小白选择公园吧。

输入输出格式

输入格式:

第一行,两个整数 NNN 和 MMM ,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来 NNN 行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来 MMM 行,每行三个整数。第一个整数 KKK , 111 或 222 。

  • K=1K=1K=1 表示,小新要带小白出去玩,接下来的两个整数 aaa 和 bbb 给出了选择公园的范围( 1≤a,b≤N1≤a,b≤N1≤a,b≤N );
  • K=2K=2K=2 表示,小白改变了对某个公园的打分,接下来的两个整数 ppp 和 sss ,表示小白对第 ppp 个公园的打分变成了 sss ( 1≤p≤N1≤p≤N1≤p≤N )。
    其中, 1≤N≤5000001≤N≤500 0001≤N≤500000 , 1≤M≤1000001≤M≤100 0001≤M≤100000 ,所有打分都是绝对值不超过 100010001000 的整数。

输出格式:

小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。

输入输出样例

输入样例#1:

5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
输出样例#1:

2
-1

Solution:

  本题实在是鬼~~(善用结构体啊!又是调半天不出来的题~)

  经典的带修改的区间最大连续子段和问题,典型的线段树嘛~!

  写了一个数组版线段树,不知道查询怎么去维护了,最后还是借鉴别人的代码,学了一波结构体写线段树的风格。

  建一棵线段树维护一下信息:$lmx$(与左边界相连的最大连续子段和),$rmx$(与右端点相连的最大连续子段和),$all$(整个区间的最大连续子段和),$sum$(整个区间的和)。

  那么还是正常的单点修改,只不过每次$pushup$自下而上维护节点$rt$的信息时,需要这些操作:

  1、当左儿子$ls$的$rmx$和右儿子$rs$的$lmx$均为$<0$时,整个区间的最大连续子段和$rt.all$直接取$Max(rs.lmx,ls.rmx)$。否则$rt.all$加上左右儿子中不为负值的$ls.rmx,rs.lmx$,然后$rt.all$再与单独的$ls.all$和$rs.all$中取最大值。

  2、当前节点$rt$的与左端点相连的最大连续子段和,在左儿子$ls.lmx$和右儿子$rs.lmx+ls.sum$中取最大值。

  3、同理当前节点$rt$的与右端点相连的最大连续子段和,在右儿子$rs.rmx$和左儿子$ls.rmx+rs.sum$中取最大值。

  4、不要忘了维护整个区间的和,$rt.sum=ls.sum+rs.sum$。

  (注意$pushup$函数的变量为结构体,左右儿子定义为$const node &ls$和$const node &rs$,因为查询时不能确定一段区间的最大连续子段和,所以需要想$pushup$函数一样更新一下整个区间的信息,定义变量为结构体能方便后面查询维护区间最大子段和,加$const$是因为$ls,rs$本身也是个变量)

  再讲下写的吐血的查询(注意坑点,区间可能$l>r$),整个递归过程参考了神犇的代码(这个结构体的递归写的太美妙了~!),首先将一段区间分为多个小区间,当区间包含时直接返回当前区间,然后每次递归向上用$pushup$维护整段查询的区间,引入一个结构体变量$a$记录整段区间的值。最后输出的是返回结构体变量的成员$all$(即该区间的最大连续子段和)。

  (写完此题,又“深度”理解了一波线段树~唉~太菜了`~)

代码:

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=;
int n,m;
struct node{
ll sum,lmx,rmx,all;
}t[N<<];
il int gi(){
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
return f?-a:a;
}
il void pushup(node &rt,const node &ls,const node &rs){
if(ls.rmx<&&rs.lmx<)rt.all=Max(ls.rmx,rs.lmx);
else {
rt.all=;
if(ls.rmx>)rt.all+=ls.rmx;
if(rs.lmx>)rt.all+=rs.lmx;
}
rt.all=Max(rt.all,Max(ls.all,rs.all));
rt.lmx=Max(ls.lmx,ls.sum+rs.lmx);
rt.rmx=Max(rs.rmx,rs.sum+ls.rmx);
rt.sum=ls.sum+rs.sum;
}
il void build(int l,int r,int rt){
if(l==r){t[rt].all=t[rt].sum=t[rt].lmx=t[rt].rmx=gi();return;}
int m=l+r>>;
build(lson),build(rson);
pushup(t[rt],t[rt<<],t[rt<<|]);
}
il void update(int L,int c,int l,int r,int rt){
if(l==r){t[rt].all=t[rt].sum=t[rt].lmx=t[rt].rmx=c;return;}
int m=l+r>>;
if(L<=m)update(L,c,lson);
else update(L,c,rson);
pushup(t[rt],t[rt<<],t[rt<<|]);
}
il node query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r)return t[rt];
int m=l+r>>;
if(L<=m&&R>m){node a;pushup(a,query(L,R,lson),query(L,R,rson));return a;}
else if(L<=m)return query(L,R,lson);
return query(L,R,rson);
}
int main(){
n=gi(),m=gi();
build(,n,);
int k,x,y,c;
while(m--){
k=gi();
if(k==){x=gi(),y=gi();if(x>y)swap(x,y);printf("%lld\n",query(x,y,,n,).all);}
else {x=gi(),c=gi(),update(x,c,,n,);}
}
return ;
}

P4513 小白逛公园的更多相关文章

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

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

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

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

  3. luogu P4513 小白逛公园 (区间合并)

    链接:https://www.luogu.org/problemnew/show/P4513 思路: 很基础的区间合并,开四个数组: num: 区间数字的和 lsum:从左端点起最大连续字段和 rsu ...

  4. P4513 小白逛公园 动态维护最大子段和

    题目链接:https://www.luogu.org/problem/P4513 #include<iostream> #include<cstdio> #include< ...

  5. 洛谷P4513 小白逛公园

    区间最大子段和模板题.. 维护四个数组:prefix, suffix, sum, tree 假设当前访问节点为cur prefix[cur]=max(prefix[lson],sum[lson]+pr ...

  6. 2018.07.23 洛谷P4513 小白逛公园(线段树)

    传送门 线段树常规操作了解一下. 单点修改维护区间最大连续和. 对于一个区间,维护区间从左端点开始的连续最大和,从右端点开始的连续最大和,整个区间最大和,区间和. 代码如下: #include< ...

  7. P4513 小白逛公园 (线段树)

    题目链接 Solution 线段树是一门比较刁钻的手艺... 此题我们需要维护 \(4\) 个变量: \(amx\) 代表当前节点的最大值. \(lmx\) 代表当前节点以左端点为起点的区间最大值. ...

  8. 洛谷P4513 小白逛公园 (线段树)

    这道题看起来像是线段树和最大子段和的结合,但这里求最大子段和不用dp,充分利用线段树递归的优势来处理.个人理解:线段树相当于把求整个区间的最大子段和的问题不断划分为很多个小问题,容易解决小问题,然后递 ...

  9. [vijos P1083] 小白逛公园

    不知怎地竟有种错觉此题最近做过= =目测是类似的?那道题貌似是纯动归? 本来今晚想做两道题的,一道是本题,一道是P1653疯狂的方格取数或NOI08 Employee,看看现在的时间目测这个目标又达不 ...

随机推荐

  1. css3媒体查询中device-width和width的区别

    1.device-width 定义:定义输出设备的屏幕可见宽度. 不管你的网页是在safari打开还是嵌在某个webview中,device-width都只跟你的设备有关,如果是同一个设备,那么他的值 ...

  2. IBM MQ Explore使用

    一,版本说明: 系统:win10.MQ:V9.04 二.关于帮助文档: 1.读了差不多一大半,个人感觉说明的比较生僻,应该是直译过来的.但是还是可以从这里面学一下基本的操作. 2.对于一些基本的操作, ...

  3. 高性能可扩展MySQL数据库设计及架构优化 电商项目(慕课)第3章 MySQL执行计划(explain)分析

    ID:相同就从上而下,不同数字越大越优先

  4. Nginx+proxy_cache图片缓存

    搭建图片缓存机制的原理在于减少数据库的负担并加快静态资源的响应. 步骤: 1. vim /usr/local/nginx/conf/nginx.conf 2. http{     ...     .. ...

  5. 爬虫 xpath etree自动补全页面

    aa = etree.HTML(response.content) bb = etree.tostring(aa) doc = etree.HTML(bb)

  6. mod_deflate模块

    mod_deflate模块 压缩模块,使用mod_deflate模块压缩页面优化传输速度 主要是需要设置 1.针对的内容 2.压缩比是多少 可以忽略排除特定旧版本的浏览器的设置.因为那些都太老了,现在 ...

  7. java的模运算

    在学习某个加密算法的时候留意到模运算,仔细查了资料后才注意到Java中的 % 其实是取余而不是取模,但是百度的时候找到的很多文章都把Java的 % 直接当成取模来用了,为了少踩坑所以自己整理了一下写了 ...

  8. 十、Linux vi/vim

    Linux vi/vim 所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主 ...

  9. nodejs实现前后端交互

    本人nodejs入门级选手,站在巨人(文殊)的肩膀上学习了一些相关知识,有幸在项目中使用nodejs实现了前后端交互,因此,将整个交互过程记录下来,方便以后学习. 本文从宏观讲述nodejs实现前后端 ...

  10. 2017 United Kingdom and Ireland Programming(Gym - 101606)

    题目很水.睡过了迟到了一个小时,到达战场一看,俩队友AC五个了.. 就只贴我补的几个吧. B - Breaking Biscuits Gym - 101606B 旋转卡壳模板题.然后敲错了. 代码是另 ...