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

题目大意:给你n个数,让你找出一个区间中f的最大值,具体的f计算方法,这段区间的和乘以这段区间的最小值。

具体思路:我们枚举每个位置,对于当前位置的数,通过二分 找出这个数作为区间最小值能够到达的最左端和最右端。如果是正数,我们直接a[i]*这段区间和就可以了,因为都是正数。

如果当前的a[i]是负数,对于这个点的右段,我们找出一个前缀和最小的点,然后对于这个点的左端,我们找出一个前缀和最大的,这样就能保证选定的区间是最小的了,负数*负数=正数。

预处理出前缀和在每段区间的最小值,最大值,以及每个区间中a[i]的最小值。

感谢qyn的讲解。

AC代码:

 #include<bits/stdc++.h>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
const int maxn = 5e5+;
ll dp1[maxn][],dp2[maxn][],dp3[maxn][];
ll a[maxn];
ll qian[maxn];
int n;
void RMQ1()
{
for(int i=; i<=; i++)
{
for(int j=; j<=n; j++)
{
if(j+(<<i)-<=n)
{
dp1[j][i]=min(dp1[j][i-],dp1[j+(<<(i-))][i-]);
}
}
}
}
void RMQ2()
{
for(int i=; i<=; i++)
{
for(int j=; j<=n; j++)
{
if(j+(<<i)-<=n)
{
dp2[j][i]=max(dp2[j][i-],dp2[j+(<<(i-))][i-]);
}
}
}
}
void RMQ3()
{
for(int i=; i<=; i++)
{
for(int j=; j<=n; j++)
{
if(j+(<<i)-<=n)
{
dp3[j][i]=min(dp3[j][i-],dp3[j+(<<(i-))][i-]);
}
}
}
}
bool judge(int l,int r,ll val)
{
int k=;
k=(int)log2((double)(r-l+));
ll tmp=min(dp1[l][k],dp1[r-(<<k)+][k]);
return tmp==val;
}
int Find_l(int pos)
{
int l=,r=pos;
int ans=pos;
while(l<=r)
{
int mid=(l+r)>>;
if(judge(mid,pos,a[pos]))
{
ans=mid;
r=mid-;
}
else
l=mid+;
}
return ans;
}
int Find_r(int pos)
{
int l=pos,r=n;
int ans=pos;
while(l<=r)
{
int mid=(l+r)>>;
if(judge(pos,mid,a[pos]))
{
ans=mid;
l=mid+;
}
else
r=mid-;
}
return ans;
}
int get_max(int l,int r)
{
int k=;
k=(int)log2((double)(r-l+));
ll tmp=max(dp2[l][k],dp2[r-(<<k)+][k]);
return tmp;
}
int get_min(int l,int r)
{
int k=;
k=(int)log2((double)(r-l+));
ll tmp=min(dp3[l][k],dp3[r-(<<k)+][k]);
return tmp;
}
int main()
{
scanf("%d",&n);
for(int i=; i<=n; i++)
{
scanf("%lld",&a[i]);
dp1[i][]=a[i];
qian[i]=qian[i-]+a[i];
dp2[i][]=dp3[i][]=qian[i];
}
RMQ1(); /// 区间最小值,在每一次询问的时候求出最左边的端点和最右边的端点
RMQ2();/// 前缀和最大值
RMQ3(); /// 前缀和最小值
ll ans=;
for(int i=; i<=n; i++)
{
int t1=Find_l(i);
int t2=Find_r(i);
if(a[i]>)
ans=max(ans,(qian[t2]-qian[t1-])*a[i]);
else
{
ans=max(ans,a[i]*(get_min(i,t2)-get_max(t1,i)));
}
}
printf("%lld\n",ans);
return ;
}

最新文章

  1. python 的异常及其处理
  2. Oracle日期格式转换
  3. 51nod lyk与gcd
  4. (六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型)
  5. python获取命令行参数的方法
  6. iOS - UIImageView
  7. js Touch事件(向左滑动,后退)
  8. Cortex-A9 UART
  9. php-GD库函数(三)
  10. 携程Java工程师——一道面向对象面试选择题(转)
  11. Android studio的那些bug
  12. 【BZOJ3143】游走(高斯消元,数学期望)
  13. True和数字相加的结果
  14. XA-分布式事物
  15. Confluence 6 后台中的选择站点首页
  16. BZOJ1898 [Zjoi2005]Swamp 沼泽鳄鱼 矩阵
  17. 常见的原生javascript DOM操作
  18. POJ 2498
  19. 数据分析——Matplotlib图形绘制
  20. IE盒模型和W3C盒子模型的区别

热门文章

  1. SQL CREATE TABLE 语句
  2. .NET平台下,初步认识AutoMapper
  3. SQL其他常用的语句
  4. Ubuntu安装mysql之后,编译找不到头文件
  5. 小程序——阿里服务器配置https及什么是IIS
  6. 08-JavaScript中的函数
  7. react性能优化
  8. Magento Meigee-Glam 主题的用法
  9. python学习日记(OOP——静态方法和类方法)
  10. 忘掉Ghost!利用Win10自带功能,玩转系统备份&amp;恢复 -- 关于系统恢复的深度思考