本文主要是介绍单调栈--poj2796 Feel good,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
给定数列,求一个区间内最小值乘区间和,的最大值。
ps:1.最大值可能是0
2.前缀和也是long long
3.手写栈
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;
struct node{
int v;
int l,r;//表示v是[l,r]内的最小值
}a[maxn],t;
ll presum[maxn];
node stk[maxn];
int p = 0;
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n ; i ++) {
scanf("%d",&a[i].v);
a[i].l = a[i].r = i;//初始化(v,i,i)v至少是[i,i]内的最小值
presum[i] = presum[i - 1] + a[i].v;
}
ll ans = -1,tmp = 0;//最大值可能为0
int ans_l = 0,ans_r = 0;
stk[p ++] = a[1];
for (int i = 2; i <= n; i ++) {
if(a[i].v >= stk[p - 1].v) stk[p ++] = a[i];//相等也放上去好了
else {
while (p > 0 && stk[p - 1].v > a[i].v) {//可知t > top,a[i] > top,t > a[i],用来更新[l,r],并且总是在出栈时更新
t = stk[p - 1];p --;
if(p > 0){
stk[p - 1].r = t.r;
}
a[i].l = t.l;
tmp = t.v * (presum[t.r] - presum[t.l - 1]);
if(tmp > ans) {ans = tmp;ans_l = t.l,ans_r = t.r;}
}
stk[p ++] = a[i];
}
}
while (p > 0) {//最后要清空栈,最大值也可能出现在这里
t = stk[p - 1];p --;
tmp = t.v * (presum[t.r] - presum[t.l - 1]);
if(tmp > ans) {ans = tmp;ans_l = t.l,ans_r = t.r;}
if(p > 0) stk[p - 1].r = t.r;
}
printf("%lld\n",ans);
printf("%d %d\n",ans_l,ans_r);
return 0;
}
这篇关于单调栈--poj2796 Feel good的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!