您的位置:首页 > Web前端

poj2796 feel good 单调栈 前后延伸

2017-07-26 11:06 501 查看
Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people's memories about some period of life. 

A new idea Bill has recently developed assigns a non-negative integer value to each day of human life. 

Bill calls this value the emotional value of the day. The greater the emotional value is, the better the daywas. Bill suggests that the value of some period of human life is proportional to the sum of the emotional values of the days in the given period, multiplied
by the smallest emotional value of the day in it. This schema reflects that good on average period can be greatly spoiled by one very bad day. 

Now Bill is planning to investigate his own life and find the period of his life that had the greatest value. Help him to do so.

Input
The first line of the input contains n - the number of days of Bill's life he is planning to investigate(1 <= n <= 100 000). The rest of the file contains n integer numbers a1, a2, ... an ranging from 0 to 10 6 - the
emotional values of the days. Numbers are separated by spaces and/or line breaks.

Output
Print the greatest value of some period of Bill's life in the first line. And on the second line print two numbers l and r such that the period from l-th to r-th day of Bill's life(inclusive) has the greatest possible value. If
there are multiple periods with the greatest possible value,then print any one of them.

Sample Input
6
3 1 6 4 5 2


Sample Output
60
3 5

题意就是找一段区间,区间内的最小值与区间内所有数的和的乘积最大。

方法是对每一个值 大于等于它的就往两边延伸

维护一个单增栈 

向后延伸的部分:在栈顶元素被弹出时前一个元素应该向后延伸把他加上

向前延伸则是在入栈时解决的:如果一个元素入栈时小于栈顶元素 那么栈顶元素会被弹出 他向前延伸的值加上被弹出的栈顶元素的值就是该元素应该向前延伸的值

例子:一开始 3(1,1)入栈

然后 1<3入栈时要把3 弹出 弹出 后栈空 所以没有什么元素要向后延伸的 但是1<3所以它可以向前延伸

3(1,1)  1(1,2);

该6 (3,3)入栈了 比一大直接排在1后面 ,先不计算 计算都发生在元素弹出时

4(4,4)<6所以弹出6  这时1向后延伸 1(1,3) 4向前延伸4(3,4);

1(1,3)  4(3,4)

5(5,5)>4 入栈即可

1(1,3)  4(3,4) 5(5,5) <
4000
/span>

2(6,6)<5  此时弹出5 2向前延伸2(5,6)  4向后延伸(3,5)

2(3,6)<4  此时弹出4 2向前延伸(3,6) 1向后延伸(1,6)
1(1,6)  2(3,6)
这时还有两个值没有计算 要把他们全弹出 可以在最后加个-1也可以
#include <iostream>
#include<cstdio>
#include<stack>
using namespace std;
const int maxn=100005;
int tmp[maxn];
long long sum[maxn];
struct node
{
    long long num;
    int pre,next;
    int pos;
};
int main()
{
    int n;
    while(scanf("%d",&n)!=-1)
    {
        stack<node>s;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&tmp[i]);
            if(i==0)
            sum[i]=tmp[i];
            else sum[i]=sum[i-1]+tmp[i];
        }
        node tt;
        tt.next=1;
        tt.pre=1;
        tt.pos=0;
        tt.num=tmp[0];
        s.push(tt);
        long long mmax=-999,ans=0;
        int l=0,r=0;
        for(int i=1;i<n;i++)
        {
            node tmp1;
            tmp1.num=tmp[i];
            tmp1.pre=1;
            tmp1.next=1;
            tmp1.pos=i;
            while(!s.empty()&&tmp1.num<=s.top().num)   //当扫描元素比栈顶元素小时 要弹出栈顶元素并计算
            {
                tt=s.top();
                s.pop();   //栈顶元素出站
                if(!s.empty())
                s.top().next+=tt.next;    //栈顶元素要向后延伸
                tmp1.pre+=tt.pre;      //刚入栈的元素向前延伸
                ans=tt.num*(sum[tt.pos+tt.next-1]-sum[tt.pos-tt.pre]);
                if(ans>mmax)
                {
                    mmax=ans;
                    r=tt.pos+tt.next-1;
                    l=tt.pos-tt.pre+1;
                }

            }
            s.push(tmp1);
        }
            while(!s.empty())
            {
                tt=s.top();
                s.pop();
                if(!s.empty())s.top().next+=tt.next;
                 ans=tt.num*(sum[tt.pos+tt.next-1]-sum[tt.pos-tt.pre]);
                if(ans>mmax)
                {
                    mmax=ans;
                    r=tt.pos+tt.next-1;
                    l=tt.pos-tt.pre+1;
                }

            }
           printf("%lld\n%d %d\n",mmax,l+1,r+1);

    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: