poj 2796
http://poj.org/problem?id=2796
hdu 1506
http://acm.hdu.edu.cn/showproblem.php?pid=1506

这两个题一个套路 所以放在一起写了

poj 2796
题意:给出一个长度n的序列 求 max(一个区间的和乘上该区间的最小值 )
我们可以这样 遍历每一个点 把每个点作为一个区间的最小值 去维护一下左右边界
那么在加上一个前缀和处理 遍历一遍就可以得出答案了
那么仔细想想 当前点最小 向左边去找 一直到最左边的数大于该数
右边也同理

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
ll a[1000005];
ll sum[1000005];
int l[1000005], r[1000005];
int main()
{

    int n;
    cin>>n;
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", &a[i]);
        sum[i]=sum[i-1] + a[i];
    }
    int j;
    for (int i = 1; i <= n; i++)
    {
        j = i;
        while (j>1 && a[j-1]>=a[i])
            j=l[j-1];///这是代码的核心 想一下左边的值大于该点的值 那么左边的这个值的左边界
        l[i]=j;       ///是大于等于左边的值的 所以也一定在该点的区间内 大大减少了复杂度
    }
    for (int i=n;i;i--)
    {
        j=i;
        while (j<n && a[j+1]>=a[i])
            j=r[j+1];///道理同左边的处理
        r[i]=j;
    }
    ll ans = -1;
    int ansl = 0, ansr = 0;
    for (int i = 1; i <= n; i++)
    {
        ll v = a[i] * (sum[r[i]] - sum[l[i] - 1]);
        if (v > ans)
        {
            ans = v;
            ansl = l[i];
            ansr = r[i];
        }
    }
    cout<<ans<<endl<<ansl<<" "<<ansr;
    return 0;
}

hdu 1506
这题与上面一题很像 就是给了一个长度为n的序列 代表一段连续的宽为1的长方形的长 问最大连续的长方形的面积是多少 要成长方形 大家想一下木板效应就懂了 这个面积的大小取决于最短的长度 然后向两边拓展区间长度 直到有比他短的就是边界 所以这题与上面一题方法一样
以每个点作为区间最小值 去维护左右两个边界 然后去循环找最大即可 这题比起上一题仅仅是少了一个前缀和处理而已

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100010],l[100010],r[100010];
int main()
{
    int n;
    while(cin>>n && n)
    {
        for(int i=1; i <= n; i ++)
            scanf("%d",&a[i]);

        for (int i=1,j;i<=n;i++)
        {
            j=i;
            while (j>1 && a[j-1]>=a[i])
                j=l[j-1];
            l[i]=j;
        }
        for (int i=n,j;i;i--)
        {
            j=i;
            while (j<n && a[j+1]>=a[i])
                j=r[j+1];
            r[i]=j;
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,1LL * a[i] * (r[i] - l[i] + 1));
        cout<<ans<<endl;
    }
    return 0;
}