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