题目链接:https://nanti.jisuanke.com/t/38228

题目大意:一个区间的值等于该区间的和乘以区间的最小值。给出一个含有n个数的序列(序列的值有正有负),找到该序列的区间最大值。

样例输入:

5

1 2 3 4 5

样例输出:

36

解题思路:如果序列的值全部为正值的话,可以说很简单,用一个单调栈加前缀和就可以了直接a。但是区间中存在负值,这个问题就变得复杂多了。

首先我们可以用两次单调栈,在O(n)的时间内,对于每个a[i]找到一个最大区间[ l[i] , r[i] ],使得a[i]在这个区间内为最小值。

然后我们便可以枚举每一个a[i],如果a[i]大于0,我们要在区间[ l[i] , r[i] ]内找到一个子区间使得这个区间的和最大,因为这个区间的和越大就可以使得区间的值越大,因为a[i]是区间[ l[i] , r[i] ]的最小值,所以该区间所有值均为正,则子区间的最大和即为[ l[i] , r[i] ]全部数的和,用前缀和便可以求出来了。

但是如果a[i]<0的话,我们就要在[ l[i] , r[i] ]内找到一个子区间使得这个子区间的和最小,这样才能使得区间值最大,我们可以建立两颗线段树,分别维护前缀和的最大值和前缀和的最小值,再在区间[ l[i]-1 , i-1 ]用最大值线段树查找到一个点使得这个点的前缀和最大设最大前缀和为x,再在区间[ i , r[i] ]这个区间内用最小值线段树查找一个点使得这个点的前缀和最小设最小前缀和为y,这样y-x就为区间[ l[i] , r[i] ]内区间和最小的子区间和。

接下来枚举每一个a[i],求出区间值,更新ans就好了。

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int N=5e5+;
  5. int n,m,q,l[N],r[N];
  6. ll sum[N],a[N];
  7. stack<ll> st;
  8. ll tr[][N*];
  9. void pushup(int rt){
  10. tr[][rt]=max(tr[][rt<<],tr[][rt<<|]);
  11. tr[][rt]=min(tr[][rt<<],tr[][rt<<|]);
  12. }
  13. void build(int l,int r,int rt){
  14. if(l==r){
  15. tr[][rt]=tr[][rt]=sum[l];
  16. return;
  17. }
  18. int mid=(l+r)/;
  19. build(l,mid,rt*);
  20. build(mid+,r,rt*+);
  21. pushup(rt);
  22. }
  23. ll ask0(int L,int R,int l,int r ,int rt){ //查找[L,R]区间内的最大值
  24. if(L<=l&&R>=r) return tr[][rt];
  25. ll ans=-1e18;
  26. int mid=(l+r)/;
  27. if(mid>=L) ans=max(ans,ask0(L,R,l,mid,rt*));
  28. if(mid<R) ans=max(ans,ask0(L,R,mid+,r,rt*+));
  29. return ans;
  30. }
  31. ll ask1(int L,int R,int l,int r ,int rt){ //查找[L,R]区间内的最小值
  32. if(L<=l&&R>=r) return tr[][rt];
  33. ll ans=1e18;
  34. int mid=(l+r)/;
  35. if(mid>=L) ans=min(ans,ask1(L,R,l,mid,rt*));
  36. if(mid<R) ans=min(ans,ask1(L,R,mid+,r,rt*+));
  37. return ans;
  38. }
  39. int main(){
  40. cin>>n;
  41. for(int i=;i<=n;i++){
  42. cin>>a[i];
  43. sum[i]=sum[i-]+a[i];
  44. }
  45. build(,n,);
  46. for(int i=;i<=n;i++){ //单调栈找左边界
  47. while(st.size()&&a[st.top()]>=a[i])st.pop();
  48. if(st.size()) l[i]=st.top()+;
  49. else l[i]=;
  50. st.push(i);
  51. }
  52. while(st.size()) st.pop();
  53. for(int i=n;i>=;i--){ //单调栈找右边界
  54. while(st.size()&&a[st.top()]>=a[i])st.pop();
  55. if(st.size()) r[i]=st.top()-;
  56. else r[i]=n;
  57. st.push(i);
  58. }
  59. ll ans=-1e18;
  60. for(int i=;i<=n;i++){ //枚举每一个a[i]
  61. int L=l[i],R=r[i];
  62. if(a[i]<){
  63. ll x=ask0(max(L-,),max(i-,),,n,);
  64. if(L==&&x<) x=; //特判L==1的情况
  65. ll y=ask1(i,R,,n,);
  66. ans=max(ans,(y-x)*a[i]);
  67. }else ans=max(ans,(sum[R]-sum[L-])*a[i]);
  68. }
  69. cout<<ans<<endl;
  70. return ;
  71. }

The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer (单调栈+线段树)的更多相关文章

  1. The Preliminary Contest for ICPC China Nanchang National Invitational I.Max answer单调栈

    题面 题意:一个5e5的数组,定义一个区间的值为 这个区间的和*这个区间的最小值,注意数组值有负数有正数,求所有区间中最大的值 题解:如果全是正数,那就是原题 POJ2796 单调栈做一下就ok 我们 ...

  2. 计蒜客 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 ...

  3. 2019The Preliminary Contest for ICPC China Nanchang National Invitational

    The Preliminary Contest for ICPC China Nanchang National Invitational 题目一览表 考察知识点 I. Max answer 单调栈+ ...

  4. 计蒜客 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 ...

  5. The Preliminary Contest for ICPC China Nanchang National Invitational

    目录 Contest Info Solutions A. PERFECT NUMBER PROBLEM D. Match Stick Game G. tsy's number H. Coloring ...

  6. The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest

    打网络赛 比赛前的准备工作要做好 确保 c++/java/python的编译器能用 打好模板,放在桌面 A. PERFECT NUMBER PROBLEM #include <cstdio> ...

  7. The Preliminary Contest for ICPC China Nanchang National Invitational I题

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

  8. Max answer(The Preliminary Contest for ICPC China Nanchang National Invitational)

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

  9. 2019 The Preliminary Contest for ICPC China Nanchang National Invitational(A 、H 、I 、K 、M)

    A. PERFECT NUMBER PROBLEM 题目链接:https://nanti.jisuanke.com/t/38220 题意: 输出前五个完美数 分析: 签到.直接百度完美数输出即可 #i ...

随机推荐

  1. Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式

    一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...

  2. h5与c3权威指南笔记--css3结构性伪类选择器root,not,empty,target

    root:将样式绑定到根元素(html中的根元素是<html></html>) 举个栗子 :root{ background-color: yellow; } body{ ba ...

  3. Ajax常见面试题

    1,什么是ajax? 为什么要使用ajax? 1.ajax是"asynchornous javascript and xml "的缩写,指一种创建交互式网页应用的网页开发技术. 2 ...

  4. Python3 字典 items() 方法

    描述 Python 字典 items() 方法以列表返回可遍历的(键, 值) 元组数组. 语法 items()方法语法: dict.items() 参数 NA. 返回值 返回可遍历的(键, 值) 元组 ...

  5. SHA1withRSA加签名和验签名

    利用私钥加签名: //contentForSign为需加标签的字符串 public String signWhithsha1withrsa(string contentForSign) { strin ...

  6. docker-compose的安装和卸载

    使用docker-compose 可以轻松.高效的管理容器,它是一个用于定义和运行多容器 docker 的应用程序工具. 原文地址:代码汇个人博客 http://www.codehui.net/inf ...

  7. 【心得】Lattice Diamond 后端约束实战小结

    [博客导航] [导航]FPGA相关 IOB约束 参考<插入IO寄存器和位置约束---lattice&diamond>,推荐的方法是: 1.在strategy设置[Map Desig ...

  8. ASP.NET MVC2未能加载类型“System.Web.Mvc.ViewPage的解決方法

    问题描述: “/”应用程序中的服务器错误. 分析器错误 说明: 在分析向此请求提供服务所需资源时出错.请检查下列特定分析错误详细信息并适当地修改源文件. 分析器错误消息: 未能加载类型“System. ...

  9. ABP之session

    ABP提供了一个IAbpSession接口,可以在不使用ASPNET的session的情况下获取当前用户和租户.IAbpSession还被ABP中的其他结构(如设置和授权系统)完全集成和使用. 注入s ...

  10. Socket网络编程(案例)

    Socket:套接字 java.net包 1.流式套接字:基于TCP协议的Socket网络编程 工作方式: 1.客户端A连接到服务器: 2.服务器建立连接并把客户端A添加到列表: 3.客户端B.C.. ...