就是求区间和与区间最小值的积的最大值 但是a[i]可能是负的 这就很坑 赛后看了好多dalao的博客 终于a了

这个问题我感觉可以分为两个步骤

第一步是对于每个元素 以它为最小值的最大区间是什么

第二步是找出来在这个区间里面 最大的连续和多少

那么我们怎么找到第一步这个最大区间呢

可以先找这个元素左边第一个比他小的值的下标 和右边第一个比他小的值的下标 这两个下标确定了 最大区间就确定了

怎么找这个下标呢 暴力的话时间复杂度太高 是n^2 需要使用单调栈:

单调栈 顾名思义就是元素都是单调递增或者递减的栈 至于它有什么作用 接着往下看

假如有一个数组a:   3 5 1 6 2

用数组 L 表示a数组里的每一个元素 从自身位置 向左 第一个比它小的元素的位置

那么L就应该是: 0 1 0 3 3 (这里为了方便表示 我让a数组的下标从1开始标记 这样L数组里面 0 就表示左边的数都比他大 1 就表示第一个数比他小 以此类推)

那么我们怎么利用单调栈实现呢?

先将 a[0]赋值为一个极小值 -0x7ffffff,然后将0入栈

对于数组a的每一个元素 进行如下语句:

while(a[S.top()]>=a[i])
S.pop();
l[i] = S.top();
S.push(i);

while语句 保证了栈里面的数据是单调递减的

看不明白没有关系 让我们模拟一下:
i==1时 a[S.top]=a[0]=-0x7ffffff 不进入while循环

所以L[1]=0;

将1入栈 此时的栈:0 1(实际上我们比较的是a[i] 所以逻辑上来讲 此时的栈:a[0] a[1] 也就是 -0x7ffff 3 因为我们需要用到左边的下标值 所以是将下标入栈 这样既可以访问到下标所对应的值 也可以访问下标)

i==2时,a[S.top]=a[1]=3 小于5 还是不进入while循环

L[2]=S.top()=1

将2入栈 此时的栈:0 1 2(-0x7ffff  3  5 )

i==3时,a[S.top]=a[2]=5 大于1

S.pop(),a[S.top]=a[1]=3还是大于1

S.pop(),a[S.top]=a[0]=-0x7ffffff 小于1 结束循环

所以L[3]=0

将3入栈 此时的栈:0 3(-0x7ffff  1)

.........

以此类推

逻辑上栈中的元素(a[i])始终是递减的

这样我们就通过以此循环求出了L数组 也就是找到了之前说的 最大区间的左边界 找右边界也是一样的思路,只是循环的方向不同

好了现在我们完成了第一步 要进行第二步 也就是找每个区间里面的最大连续和(如果a[i]<0的话需要找最小连续和)

如果a[i]均为非负的话就很简单了 肯定是区间越长 连续和越大 但问题是a[i]是可以有负数的

那就需要分情况讨论了

我们可以开4个数组 lmax lmin rmax rmin

lmax 和 rmax 用来记录最大连续和的区间的左右下标

lmin 和 rmin 记录最小的和的左右下标

怎么更新这四个数组呢?

for(i=;i<=n;i++)
{
if(s[i-]-s[lmin[i-]-]>)
lmin[i]=i;
else
lmin[i]=lmin[i-];
if(s[i-]-s[lmax[i-]-]<)
lmax[i]=i;
else
lmax[i]=lmax[i-];
}

s[i]是前i项的和

看代码很容易理解 如果前面几项的和是正的 那就不要他 让lmin[i]=i 如果是负的 那么加上他 这样连续和就会变小

rmax和rmin只需要倒着更新就行

最后别忘了 这四个数组必须是在L数组和R数组的范围内的 相当于第一步是第二步的限制条件:

    if(a[i]<)
{
ll=max(l[i]+,lmin[i]);
rr=min(r[i]-,rmin[i]);
}
else
{
ll=max(l[i]+,lmax[i]);
rr=min(r[i]-,rmax[i]);
}

完整ac代码:

#include<bits/stdc++.h>

using namespace std;

long long i,n,ll,rr,s[],a[],lmin[],lmax[],rmin[],rmax[],l[],r[],ans;
stack<long long> S; int main()
{
cin>>n;
for(i=;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-]+a[i];
}
ans=a[]*a[];
S.push();
a[]=-0x7fffff;
a[n+]=-0x7fffff-;
for(i=;i<=n;i++)
{
while(a[S.top()]>=a[i])
S.pop();
l[i] = S.top();
S.push(i);
}
while(S.size())
S.pop();
S.push(n+);
for(i=n;i>=;i--)
{
while(a[S.top()]>=a[i])
S.pop();
r[i]=S.top();
S.push(i);
}
lmin[]=;
lmax[]=;
rmin[n]=n;
rmax[n]=n;
for(i=;i<=n;i++)
{
if(s[i-]-s[lmin[i-]-]>)
lmin[i]=i;
else
lmin[i]=lmin[i-];
if(s[i-]-s[lmax[i-]-]<)
lmax[i]=i;
else
lmax[i]=lmax[i-];
}
for(i=n-;i>=;i--)
{
if(s[rmin[i+]]-s[i]>)
rmin[i]=i;
else
rmin[i]=rmin[i+];
if(s[rmax[i+]]-s[i]<)
rmax[i]=i;
else
rmax[i]=rmax[i+];
}
for(i=;i<=n;i++)
{
if(a[i]<)
{
ll=max(l[i]+,lmin[i]);
rr=min(r[i]-,rmin[i]);
}
else
{
ll=max(l[i]+,lmax[i]);
rr=min(r[i]-,rmax[i]);
}
ans=max(ans,a[i]*(s[rr]-s[ll-]));
}
cout<<ans; }

icpc 南昌邀请赛网络赛 Max answer的更多相关文章

  1. 2019 ICPC南昌邀请赛网络赛比赛过程及题解

    解题过程 中午吃饭比较晚,到机房lfw开始发各队的账号密码,byf开始读D题,shl电脑卡的要死,启动中...然后听到谁说A题过了好多,然后shl让blf读A题,A题blf一下就A了.然后lfw读完M ...

  2. icpc 南昌邀请赛网络赛 Subsequence

    题目链接:https://nanti.jisuanke.com/t/38232 就是判断输入是不是子序列 没想到贡献了将近十几次罚时..........可以说是菜的真实了 用cin cout超时了 改 ...

  3. 2019 ICPC南昌邀请赛 网络赛 K. MORE XOR

    说明 \(\oplus x​\)为累异或 $ x^{\oplus(a)}​$为异或幂 题意&解法 题库链接 $ f(l,r)=\oplus_{i=l}^{r} a[i]$ $ g(l,r)=\ ...

  4. 南昌邀请赛网络赛 D.Match Stick Game(dp)

    南昌邀请赛网络赛 D.Match Stick Game 题目传送门 题目就会给你一个长度为n的字符串,其中\(1<n<100\).这个字符串是一个表达式,只有加减运算符,然后输入的每一个字 ...

  5. 计蒜客 38228. Max answer-线段树维护单调栈(The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer 南昌邀请赛网络赛) 2019ICPC南昌邀请赛网络赛

    Max answer Alice has a magic array. She suggests that the value of a interval is equal to the sum of ...

  6. POJ-2796 & 2019南昌邀请赛网络赛 I. 区间最大min*sum

    http://poj.org/problem?id=2796 https://nanti.jisuanke.com/t/38228 背景 给定一个序列,对于任意区间,min表示区间中最小的数,sum表 ...

  7. 2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)

    题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum.最小前缀lsum.最小后缀rsum,枚举每个数a[i] ...

  8. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  9. 2019南昌邀请赛网络赛:J distance on the tree

    1000ms 262144K   DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(N ...

随机推荐

  1. JVM平台上的响应式流(Reactive Streams)规范

    // Reactive Streams // 响应式流是一个倡议,用来为具有非阻塞后压的异步流处理提供一个标准.大家努力的目标集中在运行时环境(JVM和JavaScript)和网络协议上. 注:响应式 ...

  2. PHP面向对象和面向过程

    编程界不论是PHP.Python都有这么两种编程思想,oop面向对象.pop面向过程,这两种在功能上没有多大区别,但是在代码编写上却有很大区别.今天就记录一下面向对象和面向过程的优点.缺点.定义.实现 ...

  3. Java运行时数据区概述

    Java 虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途,如图所示: 程序计数器 程序计数器是一块比较小的内存空间,可以看作是当前线程所执行的字节 ...

  4. PyQtdeploy-V2.4 User Guide 中文 (一)

    PyQtdeploy 用户指南 目录 介绍 与V1.0+的差异 作者 证书 安装 部署过程概览 PyQt的演示 构建演示 Android IOS Linux MacOS Windos 构建系统根目录 ...

  5. Docker-compose command 有多个命令例子

    cat docker-compose.yml version: '3.4' services: klvchen: image: python_django:19.03.0 ports: - 8000: ...

  6. 基于Android的模拟点击探索

    前言 压力测试中,一般会用到自动化测试.准备写一个APP,可以记录屏幕上的点击事件,然后通过shell命令来模拟自动执行.shell指令,比较容易实现.那么,关键的一步是获取点击的坐标.对于Andro ...

  7. 【Linux】【MySQL】CentOS7安装最新版MySQL8.0.13(最新版MySQL从安装到运行)

    1.前言 框框博客在线报时:2018-11-07 19:31:06 当前MySQL最新版本:8.0.13 (听说比5.7快2倍) 官方之前表示:MySQL 8.0 正式版 8.0.11 已发布,MyS ...

  8. block的注意点

    1). 在block内部使用外部指针且会造成循环引用情况下,需要用__week修饰外部指针: __weak typeof(self) weakSelf = self; 2). 在block内部如果调用 ...

  9. CentOS 6忘记root密码的解决办法

    1.在开机启动的时候按键盘上的“E”键 或者“ESC”键,会进入如下界面 2.选择相应的内核,再次按“E”,出现下图,选择第二项,再次按“E”键 3.经过第二步,这个画面可以编辑,在信息的最后加“空格 ...

  10. cent os 7 与cent os 6 修改主机名称

    centos6 需要修改两处:一处是/etc/sysconfig/network,另一处是/etc/hosts,只修改任一处会导致系统启动异常.零时修改用hostname your-name cnet ...