题解 SP1716 【GSS3 - Can you answer these queries III】
\]
没有 Preface。
\]
维护一个长度为 \(n\) 的数列 \(A\) ,需要支持以下操作:
0 x y将 \(A_x\) 改为 \(y\) 。1 x y求 \(\max\limits_{x \leq l \leq r \leq y}{\sum_{i=l}^rA[i]}\) 。
\]
区间最大子段和 是一个非常经典的问题。
对于 整体最大子段和 来说,一般有 \(O(n)\) 的 贪心 和 分治 做法,我们讨论的重点是 分治 做法。
\(~\)
假设当前需求解最大子段和的区间是 \([l,r]\) ,令 \(mid=\left\lfloor\dfrac{l+r}{2}\right\rfloor\)
我们套路地把 \([l,r]\) 分成 \([l,mid]\) 和 \([mid+1,r]\) ,来进行分治求解:
\(~\)
首先对于形如 \([l,l]\) 的区间,就十分好处理了,这里不多说。
\(~\)
接下来,考虑下最大子段和满不满足 区间可加性 ?(\([l,mid]\) 和 \([mid+1,r]\) 的最大子段和能否推至 \([l,r]\))
显然,只维护一个最大子段和,对 左子区间 和 右子区间 的最大子段和取个 \(\max\) 是不能维护最大子段和的,因为其漏掉了 最大子段和同时包含左子区间和右子区间 的情况。
那么对于剩下的这一种情况,它是必定经过中点 \(mid\) 的,那这种情况的最大段就是 左子区间从右端点向左走的最大段 与 右子区间从左端点向右走的最大段 的并集,其值为 左子区间的后缀最大子段和 \(+\) 右子区间的前缀最大字段和 。
那我们再维护 前 \(/\) 后 缀最大子段和 ,对其三者取 \(\max\) ,最大子段和就满足区间可加性了。
维护 前 \(/\) 后 缀最大子段和 依旧可以分成 经过 \(mid\) \(/\) 不经过 \(mid\) 来讨论。
以前缀最大子段和为例,若经过 \(mid\) ,则最大段为 左子区间 与 右子区间从左端点向右走的最大段 的并集,其值为 左子区间和 \(+\) 右子区间的前缀最大子段和 ;若不经过 \(mid\) ,则最大段为 左子区间从左端点向右走的最大段 。二者取个 \(\max\) 即可。后缀最大子段和同理。
那我们再维护个 区间和 ,那 最大子段和 ,前 \(/\) 后 缀最大子段和 就都满足区间可加性了。
至于 区间和 \(......\) ,这玩意直接加就行了。
(上述内容大家可以自己画图感性理解一下
\(~\)
求解过程
约定变量:
\(sum\) : 区间和
\(lmax\) : 区间前缀最大子段和
\(rmax\) : 区间后缀最大子段和
\(wmax\) : 区间最大子段和
设函数 \(ask(l,r)\) 求的是关于区间 \([l,r]\) 的一个四元组\((\) \(sum\), \(lmax\), \(rmax\), \(wmax\) \()\)
首先有一个递归边界 \(l=r\) ,此时这四个元素均为 \(A_l\) 。
那对于一般情况,令 \(lc=ask(l,mid),rc=ask(mid+1,r)\) ,则有:
\]
\]
\]
\]
此时 \(self\) 即为 \(ask(l,r)\) 。
struct data{
int sum;
int lmax;
int rmax;
int wmax;
};
data ask(int l,int r)
{
data self;
if(l==r)
{
self.sum=self.lmax=self.rmax=self.wmax=A[l];
return self;
}
int mid=(l+r)/2;
data lc=ask(l,mid),rc=ask(mid+1,r);
self.sum=lc.sum+rc.sum;
self.lmax=max(lc.lmax,lc.sum+rc.lmax);
self.rmax=max(rc.rmax,rc.sum+lc.rmax);
self.wmax=max(max(lc.wmax,rc.wmax),lc.rmax+rc.lmax);
return self;
}
\(~\)
然后你会发现,若对于每个询问都调用一次 ask(l,r) 会稳稳 T 掉
那我 bb 这么多有什么用呢
大家仔细想想,这个分治的过程像不像某个数据结构呢?
线段树?
线段树!
是的,用线段树维护,每个节点保存的是该节点所代表的区间 \([l,r]\) 的 \((\) \(sum\), \(lmax\), \(rmax\), \(wmax\) \()\) 。
剩下的都是一些线段树基本操作了。
\]
#include<cstdio>
#include<algorithm>
#define RI register int
using namespace std;
const int SIZE=500100;
int n,m;
int a[SIZE];
struct SegmentTree{
int l,r;
int sum;
int lmax;
int rmax;
int dat;
}t[SIZE*4];
void build(int p,int l,int r)
{
t[p].l=l;t[p].r=r;
if(l==r){t[p].sum=t[p].lmax=t[p].rmax=t[p].dat=a[l];return;}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax);
t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax);
t[p].dat=max(max(t[p*2].dat,t[p*2+1].dat),t[p*2].rmax+t[p*2+1].lmax);
}
void change(int p,int x,int val)
{
if(t[p].l==t[p].r){t[p].sum=t[p].lmax=t[p].rmax=t[p].dat=val;return;}
int mid=(t[p].l+t[p].r)/2;
if(x<=mid)change(p*2,x,val);
else change(p*2+1,x,val);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
t[p].lmax=max(t[p*2].lmax,t[p*2].sum+t[p*2+1].lmax);
t[p].rmax=max(t[p*2+1].rmax,t[p*2+1].sum+t[p*2].rmax);
t[p].dat=max(max(t[p*2].dat,t[p*2+1].dat),t[p*2].rmax+t[p*2+1].lmax);
}
SegmentTree ask(int p,int l,int r)
{
if(l<=t[p].l&&t[p].r<=r)return t[p];
int mid=(t[p].l+t[p].r)/2;
if(l<=mid&&mid<r)
{
SegmentTree lc=ask(p*2,l,r),rc=ask(p*2+1,l,r),self;
self.sum=self.lmax=self.rmax=self.dat=0;
self.sum=lc.sum+rc.sum;
self.lmax=max(lc.lmax,lc.sum+rc.lmax);
self.rmax=max(rc.rmax,rc.sum+lc.rmax);
self.dat=max(max(lc.dat,rc.dat),lc.rmax+rc.lmax);
return self;
}
if(l<=mid)
return ask(p*2,l,r);
if(mid<r)
return ask(p*2+1,l,r);
}
int main()
{
scanf("%d",&n);
for(RI i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
while(m--)
{
char op[2];
int l,r;
scanf("%s%d%d",op,&l,&r);
switch(op[0])
{
case '1':{
if(l>r)swap(l,r);
printf("%d\n",ask(1,l,r).dat);
break;
}
case '0':{
change(1,l,r);
break;
}
}
}
return 0;
}
\]
题解 SP1716 【GSS3 - Can you answer these queries III】的更多相关文章
- 线段树 SP1716 GSS3 - Can you answer these queries III
SP1716 GSS3 - Can you answer these queries III 题意翻译 n 个数,q 次操作 操作0 x y把A_xAx 修改为yy 操作1 l r询问区间[l, r] ...
- SP1716 GSS3 - Can you answer these queries III 线段树
问题描述 [LG-SP1716](https://www.luogu.org/problem/SP1716] 题解 GSS 系列的第三题,在第一题的基础上带单点修改. 第一题题解传送门 在第一题的基础 ...
- SP1716 GSS3 - Can you answer these queries III
题面 题解 相信大家写过的传统做法像这样:(这段代码蒯自Karry5307的题解) struct SegmentTree{ ll l,r,prefix,suffix,sum,maxn; }; //.. ...
- SP1716 GSS3 - Can you answer these queries III(单点修改,区间最大子段和)
题意翻译 nnn 个数, qqq 次操作 操作0 x y把 AxA_xAx 修改为 yyy 操作1 l r询问区间 [l,r][l, r][l,r] 的最大子段和 题目描述 You are give ...
- SP1716 GSS3 - Can you answer these queries III - 动态dp,线段树
GSS3 Description 动态维护最大子段和,支持单点修改. Solution 设 \(f[i]\) 表示以 \(i\) 为结尾的最大子段和, \(g[i]\) 表示 \(1 \sim i\) ...
- SPOJ GSS3 Can you answer these queries III[线段树]
SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...
- 数据结构(线段树):SPOJ GSS3 - Can you answer these queries III
GSS3 - Can you answer these queries III You are given a sequence A of N (N <= 50000) integers bet ...
- 题解【SP1716】GSS3 - Can you answer these queries III
题目描述 You are given a sequence \(A\) of \(N (N <= 50000)\) integers between \(-10000\) and \(10000 ...
- 【SP1716】GSS3 - Can you answer these queries III(动态DP)
题目链接 之前用线段树写了一遍,现在用\(ddp\)再写一遍. #include <cstdio> #define lc (now << 1) #define rc (now ...
随机推荐
- mysql oracle sql获取树 父级 子级 及自己
select * from ( select t.*,d.TABLE_NAME,d.QUERY_SQL,d.data_control_col,d.id table_id,d.where_sql fro ...
- Huffman树及其编码(STL array实现)
这篇随笔主要是Huffman编码,构建哈夫曼树有各种各样的实现方法,如优先队列,数组构成的树等,但本质都是堆. 这里我用数组来存储数据,以堆的思想来构建一个哈弗曼树,并存入vector中,进而实现哈夫 ...
- 云资源中的低成本战斗机——竞价实例,AWS、阿里云等六家云厂商完全用户使用指南
云端资源价格 预留实例:长期持有,批发路线,价格最便宜. 按需实例:即买即用,零售路线,价格最贵. 这两种资源,基于不同区域/价格的六家云厂商价格对比,连同原始数据文档我们已经打包成了一份电子文档,有 ...
- 【DPDK】【ring】从DPDK的ring来看无锁队列的实现
[前言] 队列是众多数据结构中最常见的一种之一.曾经有人和我说过这么一句话,叫做“程序等于数据结构+算法”.因此在设计模块.写代码时,队列常常作为一个很常见的结构出现在模块设计中.DPDK不仅是一个加 ...
- 线段树 or 并查集 (多一个时间截点)
There is a company that has N employees(numbered from 1 to N),every employee in the company has a im ...
- 《C# 爬虫 破境之道》:第二境 爬虫应用 — 第二节:以事件驱动状态、数据处理
续上一节内容,对Web爬虫进行进一步封装,通过委托将爬虫自己的状态变化以及数据变化暴露给上层业务处理或应用程序. 为了方便以后的扩展,我先定义一个蚂蚁抽象类(Ant),并让WorkerAnt(工蚁)继 ...
- Gym - 101982F 扫描线+线段树
题目链接:https://codeforces.com/gym/101982/attachments 要你求覆盖奇数次的矩形面积并,每次更新时减去原先的值即可实现奇数次有效,下推时为保证线段长度不变左 ...
- numpy 读取数据
一.CSV文件 CSV: Comma-Separated Value,逗号分隔值文件 显示:表格状态 源文件:换行和逗号分隔,逗号 列,换行 行 二.读取数据 1.方法 loadtxt(fname, ...
- Identity 4 -1创建一个登录中心
准备知识 官网地址:https://identityserver4.readthedocs.io/ 通过nuget安装 Identity Server4
- ssh隧道使用
在内网中几乎所有的linux服务器和网络设备都支持ssh协议.一般情况下,ssh协议是允许通过防火墙和边界设备的,所以经常被攻击者利用.同时ssh协议的传输过程是加密的,所以我们很难区分合法的ssh会 ...