题目地址:https://nanti.jisuanke.com/t/38228

题意:


给出数字序列,定义一个区间内的value值是这个区间所有数之和*这个区间的最小数,求对于这个数字序列,最大的value值

解题思路:


本题为https://blog.csdn.net/Cassie_zkq/article/details/89792443的进阶题。

对正数和负数分开处理。

对于正数a[i],利用单调栈寻找以a[i]为最小值的区间,利用前缀和数组求区间和再*a[i] 即结果

但是对于负数,只有它的区间和最小对应的这个区间的value值才最小,又由区间和=sum[j]-sum[i]可知,sum[j]最小,sum[i]最大时才能时这个区间和最小,所以问题的关键转化为寻找最小的sum[j]和最大的sum[i]

对于负数a[k](数组从下标为1开始存),  i的位置位于【0,k】,j的位置位于【k,n】,即使a[k]不是这个区间的最小值,之后也会有真正的最小值与sum[i]和sum[j]匹配来更新最大的value值,求区间的最值可以用st表,O(nlogn)的预处理时间,O(1)的查询时间

注意:如果数字序列为-1 -2 -3 -4 -5 那么sum[i]是可以为0的,所以i的位置位于【0,k】而不是【1,k】,否则sum[i]就会变成-1,会WA

找一个数左侧第一个小于等于它和右侧第一个小于它的数的单调栈模版(比两个for循环遍历代码量少,也不难理解)

    int top=0,s[maxn];s[0]=0;for(int i=1;i<=n;i++){while(top>0 && a[i]<a[s[top]])//待入栈的小于栈顶元素,那么待入栈的元素就是栈顶元素右侧第一个比它(指栈顶元素)小的数{rb[s[top]]=i;//右侧第一个小于ta的top--;}lb[i]=s[top];//左侧第一个小于等于ta的(有重复的数字对结果并不会产生什么影响)//栈内从小到大有序排列,栈顶元素是要入栈元素左侧第一个小于等于它(指要入栈的元素)的数s[++top]=i;}while(top>0){rb[s[top]]=n+1;top--;}

ac代码:


找正数区间去处理正数(emmm可以跳过这个代码直接看下一个,其实不用单独找正数区间的)

#include <iostream>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <sstream>
#define maxn 600005
typedef long long ll;
using namespace std;
ll a[maxn],sum[maxn]={0},min_sum[maxn][20],max_sum[maxn][20],lb[maxn],rb[maxn];
ll n,ans=-1;
void rmq()
{for(int i=1;i<=n;i++)min_sum[i][0]=max_sum[i][0]=sum[i];for(int j=1;(1<<j)<=n;j++)//长度{for(int i=0;i+(1<<j)-1<=n;i++){min_sum[i][j]=min(min_sum[i][j-1],min_sum[i+(1<<(j-1))][j-1]);max_sum[i][j]=max(max_sum[i][j-1],max_sum[i+(1<<(j-1))][j-1]);}}
}
void zhengshu()
{int l=1,r;while(1){while(a[l]<=0 && l<=n) l++;//寻找正数区间的左边界,a[l]>0 或者a[n]<=0if(a[l]>0){r=l;while(a[r+1]>0 && r<n) r++;//r为正数区间的右边界int top=0,s[maxn];s[0]=l-1;for(int i=l;i<=r;i++){while(top>0 && a[i]<a[s[top]])//右侧第一个小于{rb[s[top]]=i;top--;}lb[i]=s[top];//左侧第一个小于等于s[++top]=i;}while(top>0){rb[s[top]]=r+1;top--;}for(int i=l;i<=r;i++)ans=max(ans,(sum[rb[i]-1]-sum[lb[i]])*a[i]);l=r+1;}if(l>n) return ;}
}
void fushu()
{ll minn,maxx;for(int i=1;i<=n;i++){if(a[i]<0){int k1=(int)(log(i-0+1)/log(2.0));maxx=max(max_sum[0][k1],max_sum[i-(1<<k1)+1][k1]);int k2=(int)(log(n-i+1)/log(2.0));minn=min(min_sum[i][k2],min_sum[n-(1<<k2)+1][k2]);//cout<<maxx<<" "<<minn<<endl;ans=max(ans,(minn-maxx)*a[i]);}}
}
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];}rmq();zhengshu();fushu();printf("%lld",ans);return 0;
}

不去找正数区间(找一个数右侧第一个比他小的和左侧第一个小于等与它的合并代码!!)

推荐这种方法,代码简单

#include <iostream>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <sstream>
#define maxn 600005
typedef long long ll;
using namespace std;
ll a[maxn],sum[maxn]={0},min_sum[maxn][20],max_sum[maxn][20],lb[maxn],rb[maxn];
ll n,ans=-1;
void rmq()
{for(int i=1;i<=n;i++)min_sum[i][0]=max_sum[i][0]=sum[i];for(int j=1;(1<<j)<=n;j++)//长度{for(int i=0;i+(1<<j)-1<=n;i++){min_sum[i][j]=min(min_sum[i][j-1],min_sum[i+(1<<(j-1))][j-1]);max_sum[i][j]=max(max_sum[i][j-1],max_sum[i+(1<<(j-1))][j-1]);}}
}
void zhengshu()
{int top=0,s[maxn];s[0]=0;for(int i=1;i<=n;i++){while(top>0 && a[i]<a[s[top]]){rb[s[top]]=i;//右侧第一个小于ta的top--;}lb[i]=s[top];//左侧第一个小于等于ta的(有重复的数字对结果并不会产生什么影响)s[++top]=i;}while(top>0){rb[s[top]]=n+1;top--;}for(int i=1;i<=n;i++)if(a[i]>0)ans = max(ans, (sum[rb[i] - 1] - sum[lb[i]]) * a[i]);
}
void fushu()
{ll minn,maxx;for(int i=1;i<=n;i++){if(a[i]<0){int k1=(int)(log(i-0+1)/log(2.0));maxx=max(max_sum[0][k1],max_sum[i-(1<<k1)+1][k1]);int k2=(int)(log(n-i+1)/log(2.0));minn=min(min_sum[i][k2],min_sum[n-(1<<k2)+1][k2]);ans=max(ans,(minn-maxx)*a[i]);}}
}
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];}rmq();zhengshu();fushu();printf("%lld",ans);return 0;
}

【2019南昌邀请赛网络赛I:】Max Answer(st表+单调栈(新模版)+分析)相关推荐

  1. 【计蒜客 - 2019南昌邀请赛网络赛 - I】Max answer(单调栈,RMQ)

    题干: Alice has a magic array. She suggests that the value of a interval is equal to the sum of the va ...

  2. 2019南昌邀请赛网络赛

      A. PERFECT NUMBER PROBLEM 这题没什么要说的. #include<bits/stdc++.h>using namespace std;int main(){co ...

  3. 【计蒜客 - 2019南昌邀请赛网络赛 - H】Coloring Game(找规律,思维dp)

    题干: David has a white board with 2 \times N2×N grids.He decides to paint some grids black with his b ...

  4. 【计蒜客 - 2019南昌邀请赛网络赛 - K】MORE XOR(数学,找规律,打表)

    Given a sequence of nn numbers a_1, a_2, \cdots, a_na1​,a2​,⋯,an​ and three functions. Define a func ...

  5. 【计蒜客 - 2019南昌邀请赛网络赛 - M】Subsequence(字典树,dp预处理)

    题干: Give a string SS and NN string T_iTi​ , determine whether T_iTi​ is a subsequence of SS. If ti i ...

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

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

  7. 【2019南昌邀请赛现场赛 - G】Winner(思维、图论+缩点)

    题目链接: https://nanti.jisuanke.com/t/40259" Ichuan really likes to play games, so he organized a ...

  8. New Year and Old Subsequence CodeForces - 750E(线段树+矩阵dp)2019南昌icpc网络赛Hello 2019

    A string t is called nice if a string "2017" occurs in t as a subsequence but a string &qu ...

  9. 【2019南昌邀请赛现场赛 - G】Winner(建图,tarjan缩点 或 贪心)

    题目大意: n个人参加竞技比赛.比赛由三种模式a,b,c,每个人在每种模式下有对应的权值a[i]b[i]c[i].举行n−1场比赛,每场比赛主办方可以选择两个人决斗,能力值低的人淘汰.这样保证n-1场 ...

  10. 【2019南昌邀请赛现场赛 - J】Prefix(STLmap,思维)

    题干: yah has n strings <s1​,⋯,sn​>, and he generates a sequence P by two steps: P=<s1​,⋯,sn​ ...

最新文章

  1. 聊一聊今年实例分割领域的进展和未来展望
  2. mysql 字段属性命令_mysql 操作字段 命令
  3. (22)Ajax的基本使用(实现登录功能和局部刷新以及防止跨站请求伪造攻击)
  4. 计算机英语课程 ppt,Unit 3_计算机专业英语_doc_大学课件预览_高等教育资讯网
  5. 更改应用程序图标_【iOS12人机交互指南】6.2-应用图标
  6. Code First :使用Entity. Framework编程(7) ----转发 收藏
  7. 你看不懂的spring原理是因为不知道这几个概念
  8. 如何成为呼叫中心客服老司机
  9. nx set 怎么实现的原子性_正确地使用Redis的SETNX实现锁机制
  10. leetcode109. 有序链表转换二叉搜索树(深度优先搜索/快慢指针)
  11. 05-按钮的基本使用-开发步骤
  12. mysql数据库kj_Python3.7和数据库MySQL 8.0.12 数据库SQLite3连接(三)
  13. PHP新闻APP,【优速软件】APP/小程序接口:全部新闻列表,POSCMS,CodeIgniter技术文档,PHP开发文档,迅睿CMS框架官方教程...
  14. java 循环赛问题_分治法实现循环赛日程表问题
  15. 【笔记环境】Typora+Joplin+PicGo+Gitee+Onedrive
  16. 聚类分析入门(理论)
  17. 计算机软件考试难,计算机技术与软件专业技术资格考试难吗
  18. C++洛谷题解(17)——P5713
  19. unity怪物攻击玩家减血_Unity-塔防游戏之怪物波次简单算法
  20. android仿ppt,android 仿ppt进入动画效果合集

热门文章

  1. pr生成html文件格式,pr支持哪些格式
  2. MyBatis学习后篇
  3. Android篮球计分器App
  4. mybatis中的动态Sql略解,基础理解,为什么要使用动态sql,动态sql相比于传统sql的区别;仅作笔记,如有错误请及时指出
  5. php 深入,深入PHP解耦的三重境界(浅谈服务容器)
  6. lhdc协议是什么_无线耳机标注的编码是什么意思?看懂了会少很多坑
  7. ASP.NET的Session会导致的性能问题
  8. 一文读懂如何用深度学习实现网络安全
  9. 0920 - 积极休息
  10. 《Android UI基础教程》——1.4节工具