区间最小值乘以区间间和

拜拜、爱过 提交于 2020-02-12 20:09:13

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 ;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!