POJ2796【单调栈】

题意:
题意:n个数,求某段区间的最小值*该段区间所有元素之和的最大值
思路:
主要参考:http://www.cnblogs.com/ziyi–caolu/archive/2013/06/23/3151556.html
首先我们假设第i个元素是最小的话,那么他的区间是确定的,所以值也是确定的。
然后就是利用栈(单调栈),对于每个位置,搞一个前最远,后最远,然后出栈更新,再入栈。
感觉就是个利用栈,并且维护这个栈是从栈顶到栈底是单调递增的,存了起来操作。当不是单调递增的时候,栈里的值比他小的就要拿出来,让他更新,然后还要当前栈顶和刚刚拿出来的next更新,具体看代码;
PS:G++AC,C++TLE;

//#include <bits/stdc++.h>
#include<cstdio>
#include<stack>
#include<algorithm>
using namespace std;

typedef long long LL;
const int N=1e5+10;

struct asd{
    LL pre;
    LL num;
    LL next;
    LL k;
};
int n;
stack<asd>q;
LL str[N],t[N];

int main()
{
    while(!q.empty())
        q.pop();
    LL ans=-1;
    LL sum=-1;
    LL num;
    asd tmp;
    scanf("%d",&n);
    str[0]=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&t[i]);
        str[i]=str[i-1]+t[i];
    }
    tmp.num=t[1];
    tmp.pre=tmp.next=1;
    tmp.k=1;
    q.push(tmp);
    LL x=0,y=0;
    for(LL i=2;i<=n;i++)
    {
        asd tmp1;
        tmp1.num=t[i];
        tmp1.pre=tmp1.next=1;
        tmp1.k=i;
        while(!q.empty()&&tmp1.num<=q.top().num)//如果说这个元素是小于栈顶的,那么它里面的栈就要被更新,这个元素的pre也要被更新
        {
            tmp=q.top();
            q.pop();
            if(!q.empty())
                q.top().next+=tmp.next;
            tmp1.pre+=tmp.pre;
            ans=tmp.num*(str[tmp.k+tmp.next-1]-str[tmp.k-tmp.pre]);
            if(ans>=sum)
            {
                sum=ans;
                x=tmp.k-tmp.pre+1;
                y=tmp.k+tmp.next-1;
            }
        }
        q.push(tmp1);
    }
    while(!q.empty())
    {
        tmp=q.top();
        q.pop();
        if(!q.empty())
            q.top().next+=tmp.next;
        ans=tmp.num*(str[tmp.k+tmp.next-1]-str[tmp.k-tmp.pre]);
        if(ans>=sum)
        {
            sum=ans;
            x=tmp.k-tmp.pre+1;
            y=tmp.k+tmp.next-1;
        }
    }
    printf("%lld\n%lld %lld\n",sum,x,y);
    return 0;
}


posted @ 2016-09-08 21:30  see_you_later  阅读(180)  评论(0编辑  收藏  举报