http://poj.org/problem?id=2796
题意:给出一个序列,求出一个子序列,使得这个序列中的最小值乘以这个序列的和的值最大。
解法:单调递增栈:每一个元素进栈前将元素剔除的过程是该元素在向左扩展,每一个元素在站内被某一元素剔除的过程为该元素的右扩展。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <vector>
//#include <bits/stdc++.h>
#define ME(x , y) memset(x , y , sizeof(x))
#define SC scanf
#define rep(i ,j , n) for(int i = j ; i < n ; i ++)
#define INF 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
using namespace std;
typedef long long ll ;
const int maxn = 100009;
struct node{
ll val , l , r ;//该元素值,和左右扩展
}a[maxn];
ll sum[maxn];
int main()
{
stack<node>s;
int n ;
while(~scanf("%d" , &n))
{
memset(sum , 0 , sizeof(sum));
rep(i , 1 , n+1){
scanf("%lld" , &a[i].val);
sum[i] = sum[i-1]+a[i].val;//前缀和
a[i].l = a[i].r = i ;
}
ll l = INF, r = -INF , ans = -1 , ml , mr;
a[n+1].val = -INF;
rep(i , 1 , n+2){
while(!s.empty() && s.top().val >= a[i].val){
//s.top().l = min(l , s.top().l) ;
s.top().r = max(s.top().r , r);//把上下两句划掉也ac,印证了我在上面说的单调栈的原理
l = s.top().l , r = s.top().r;
ll temp = (sum[s.top().r] - sum[s.top().l-1])*(s.top().val);
if(ans < temp){
ml = l , mr = r , ans = temp;
}
s.pop();
}
a[i].l = min(l , a[i].l) ;
//a[i].r = max(a[i].r , r);
l = INF, r = -INF;
s.push(a[i]);
}
cout << ans << endl;
cout << ml << " " << mr << endl;
}
return 0 ;
}
来源:https://www.cnblogs.com/nonames/p/12300381.html