avatar
fireworks99
keep hungry keep foolish

POJ 2796 Feel Good(单调栈)

Description

给出一个序列,要求的是一个区间,这个区间的最小值乘以这个区间所有数字的和是最大值。求这个最大值与这个区间。

单调栈+前缀和

#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
const int N = 100100;

int h[N];
int L[N], R[N];
ll sum[N];
stack<int> sk;

///单调栈维护了一个单调递增序列
///单调栈:栈内越靠近栈顶的下标所对应的高度越高
///但栈内所存的,终究还是下标
int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        memset(sum, 0, sizeof(sum));
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &h[i]);
            sum[i] = sum[i - 1] + h[i];
        }

        while(!sk.empty())
            sk.pop();

        for(int i = 1; i <= n; ++i)
        {
            while(!sk.empty() && h[sk.top()] >= h[i])
                sk.pop();

            if(sk.empty())
                L[i] = 0;///最小下标 - 1
            else
                L[i] = sk.top();
            sk.push(i);
        }

        while(!sk.empty())
            sk.pop();

        for(int i = n; i >= 1; --i)
        {
            while(!sk.empty() && h[sk.top()] >= h[i])
                sk.pop();

            if(sk.empty())
                R[i] = n + 1;///最大下标 + 1
            else
                R[i] = sk.top();
            sk.push(i);
        }

        ll ans = 0, tem = 0, ansL = 1, ansR = 1;///初始化是针对'0'的,想好了再写
        for(int i = 1; i <= n; ++i)
        {
            tem = h[i] * (sum[ R[i] - 1 ] - sum[ L[i] ]);
            if(ans < tem)
            {
                ans = tem;
                ansL = L[i] + 1;
                ansR = R[i] - 1;
            }
        }
        cout << ans << '\n';
        cout << ansL << ' ' << ansR << '\n';
    }
    return 0;
}

注意初始化的值,注意if(empty)时的赋值

分别是:最小下标 - 1,最大下标 + 1

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy