P4513 小白逛公园 (线段树)
题目链接
Solution
线段树是一门比较刁钻的手艺...
此题我们需要维护 \(4\) 个变量:
- \(amx\) 代表当前节点的最大值.
- \(lmx\) 代表当前节点以左端点为起点的区间最大值.
- \(rmx\) 代表当前节点以右端点为结尾的区间最大值.
- \(sum\) 代表整段的和.
然后我们在 \(push\)_\(up\) 的时候,也是要做蛮多工作.
\(lc\) 为左端点,\(rc\) 为右端点.
\(lmx=max(lmx_{lc},sum_{lc}+lmx_{rc})\)
也就是说可以单独取左儿子里的最大值,也可以一直取到右儿子的 \(lmx\) 为止.\(rmx=max(rmx_{rc},sum_{rc}+rmx_{lc})\)
和上文同理.\(sum=sum_{lc}+sum_{rc}\)
\(amx=max(amx_{lc},amx_{rc},rmx_{lc}+lmx_{rc})\)
最关键的一步,更新每一个节点的答案. 可以在图上自己理解,此处不赘述.
特别注意,查询的时候也要把所有查出来的区间进行类似的操作...
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000008;
struct node
{
int l,r,lc,rc;
int lmx,rmx,amx,sum;
}sgm[maxn*4];
int n,m,k,x,y;
int cnt,a[maxn];
void push_up(int x)
{
int ll=sgm[x].lc,rr=sgm[x].rc;
sgm[x].sum=sgm[ll].sum+sgm[rr].sum;
sgm[x].lmx=max(sgm[ll].lmx,sgm[ll].sum+sgm[rr].lmx);
sgm[x].rmx=max(sgm[rr].rmx,sgm[rr].sum+sgm[ll].rmx);
sgm[x].amx=max(max(sgm[ll].amx,sgm[rr].amx),sgm[ll].rmx+sgm[rr].lmx);
}
void build(int l,int r,int now)
{
sgm[now].l=l;
sgm[now].r=r;
if(l==r)
{
sgm[now].lmx=sgm[now].rmx=sgm[now].sum=sgm[now].amx=a[l];
return;
}
int mid=(l+r)>>1;
sgm[now].lc=2*now;
build(l,mid,sgm[now].lc);
sgm[now].rc=2*now+1;
build(mid+1,r,sgm[now].rc);
push_up(now);
}
void change(int now,int to,int num)
{
int x=sgm[now].l,y=sgm[now].r;
if(x==y)
{
sgm[now].lmx=sgm[now].rmx=sgm[now].sum=sgm[now].amx=num;
return;
}
int mid=(x+y)>>1;
if(to<=mid) change(sgm[now].lc,to,num);
else change(sgm[now].rc,to,num);
push_up(now);
}
node query(int now,int l,int r)
{
int x=sgm[now].l,y=sgm[now].r;
if(l<=x&&r>=y) return sgm[now];
int mid=(x+y)>>1,ll=sgm[now].lc,rr=sgm[now].rc;
if(r<=mid) return query(ll,l,r);
else if(l>mid) return query(rr,l,r);
else
{
node t,t1=query(ll,l,r),t2=query(rr,l,r);
t.lmx=max(t1.lmx,t1.sum+t2.lmx);
t.rmx=max(t2.rmx,t2.sum+t1.rmx);
t.amx=max(max(t1.amx,t2.amx),t1.rmx+t2.lmx);
return t;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&k,&x,&y);
if(k==1)
{
if(x>y) swap(x,y);
printf("%d\n",query(1,x,y).amx);
}
else change(1,x,y);
}
return 0;
}
P4513 小白逛公园 (线段树)的更多相关文章
- Bzoj 1756: Vijos1083 小白逛公园 线段树
1756: Vijos1083 小白逛公园 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1021 Solved: 326[Submit][Statu ...
- Vijos 1083 小白逛公园(线段树)
线段树,每个结点维护区间内的最大值M,和sum,最大前缀和lm,最大后缀和rm. 若要求区间为[a,b],则答案max(此区间M,左儿子M,右儿子M,左儿子rm+右儿子lm). ----------- ...
- [vijos]1083小白逛公园<线段树>
描述 小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. 一开始,小白就根据公园的风景给每个公 ...
- [日常摸鱼]Vijos1083小白逛公园-线段树
题意:单点修改,询问区间最大子段和,$n\leq 5e5$ 考虑分治的方法$O(nlogn)$求一次最大子段和的做法,我们是根据中点分成左右两个区间,那么整个区间的答案要么是左边答案,要么是右边答案, ...
- 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)
P4513 小白逛公园 题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩 ...
- 线段树 || BZOJ1756: Vijos1083 小白逛公园 || P4513 小白逛公园
题面:小白逛公园 题解: 对于线段树的每个节点除了普通线段树该维护的东西以外,额外维护lsum(与左端点相连的最大连续区间和).rsum(同理)和sum……就行了 代码: #include<cs ...
- 2018.07.23 洛谷P4513 小白逛公园(线段树)
传送门 线段树常规操作了解一下. 单点修改维护区间最大连续和. 对于一个区间,维护区间从左端点开始的连续最大和,从右端点开始的连续最大和,整个区间最大和,区间和. 代码如下: #include< ...
- 洛谷P4513 小白逛公园 (线段树)
这道题看起来像是线段树和最大子段和的结合,但这里求最大子段和不用dp,充分利用线段树递归的优势来处理.个人理解:线段树相当于把求整个区间的最大子段和的问题不断划分为很多个小问题,容易解决小问题,然后递 ...
- P4513 小白逛公园
题目背景 小新经常陪小白去公园玩,也就是所谓的遛狗啦… 题目描述 在小新家附近有一条“公园路”,路的一边从南到北依次排着 nnn 个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了. 一开始,小白 ...
随机推荐
- opencv中mat矩阵如何debug
mat img 看type:img.type() rows:img.rows cols:img.cols channels:img.channels(),channels()这是一个函数,和上面两个有 ...
- axios的post请求方法---以Vue示例
Axios向后端提交数据的参数格式是json,而并非用的是form传参,post表单请求提交时,使用的Content-Type是application/x-www-form-urlencoded,而使 ...
- 空类生成对象输出的结果是什么? toString()输出 覆写Object toString()方法输出的结果是什么
空类生成对象输出的结果是什么? 输出的是对象在内存空间地址的哈希值 com.swift.P@1db9742 空类生成对象toString()输出的结果是什么? 输出的是对象在内存空间地址的哈希值的字符 ...
- C语言预处理_05
凡是以 “#”开头的均为预处理命令! 其定义的一般形式为: #define 标示符 字符串 对于宏定义说明以下几点: 1.宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种 ...
- chrome浏览器跳过(忽略)所有的js断点
在调试程序时我们经常通过打断点的方式来跟踪代码的执行流程,所以可能会在很多时候打很多断点,当我们知道了程序大概的执行流程之后,这时候断点就不太需要了.但是我们又不想马上把所有的断点清除掉,因为我们打的 ...
- linux用户和用户组管理详解
Linux 用户和用户组管理 Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统. 用户的账号一方面可以帮助 ...
- Linux学习-什么是例行性工作排程
那么 Linux 的例行性工作是如何进行排程的呢?所谓的排程就是将这些工作安排执行的流程之意! 咱们的 Linux 排程就是透过 crontab 与 at 这两个东西! Linux 工作排程的种类: ...
- POJ 3057 网络流 Evacuation
题意: 有一个n×m的房间,四周每个格子要么是墙要么是门.中间部分是墙或者人. 现在所有人要从房间逃出去,每个人的速度为1,也就是每个单位时间只能向上下左右四个方向走一格. 多个人可以站在同一个格子上 ...
- Socketserver详解
Python3中的SocketServer socket并不能多并发,只能支持一个用户,socketserver 简化了编写网络服务程序的任务,socketserver是socket的在封装.sock ...
- python - 接口自动化测试 - contants - 常量封装
# -*- coding:utf-8 -*- ''' @project: ApiAutoTest @author: Jimmy @file: contants.py @ide: PyCharm Com ...