单调栈

来源:互联网 发布:java对数学要求 编辑:程序博客网 时间:2024/03/29 16:15

通过一个例子,简要证明一下单调栈  。   poj2796

单调栈 就是维护一个栈使这个栈里面的元素是单调递增还是单调递减的!!!
那么用一个题目来理解一下他的原理。
  
这个题的意思就是说在一个[L,R]区间内,存在一个最小的数,其余的数都比它大。然后求max(这个区间的和*最小的数)。

首先维护一个单调递增的栈。设处在当前栈顶的元素为x,扫面到的当前元素为i,那么首先可以判断的是既然x处于栈顶,那么肯定a[x+1]>=a[x],然后因为i此时要入栈,那么a[i]>a[x],那么此时既然a[x+1]不在栈顶,那么肯定a[x+1]>a[i],说明最左边的大于a[i]的数应该是x+1。这是入栈的情况。。。


那么出栈呢??因为此时这个元素要出栈了,如果它的右边界再不更新,就再也没机会了,所以要更新右边界。。因为a[i]<a[x],所以a[i-1]肯定会大于a[x]即a[i-1]>a[x],即a[i-1]>a[x]>a[i],故右边界为i-1.


那么左右边界都出来了  如果一个元素始终没有出栈  说明说明????


即右边界为n。。

代码


#include<cstdio>#include<iostream>#include<algorithm>#include<stack>#include<cstring>typedef long long LL;using namespace std;const int maxn=100000+10;LL pre[maxn];int le[maxn],ri[maxn],a[maxn];struct Node{    int pos,integer;};stack<Node>s;void solve(Node tmp){    int i=tmp.pos;    int value=tmp.integer;    le[i]=i,ri[i]=-1;    Node ff;    if(!s.empty())  ff=s.top();    if(ff.integer==value)    {        le[i]=ff.pos;        s.push(tmp);        return;    }    else    {        while(!s.empty()&&ff.integer>value)        {            int pos=ff.pos;            ri[pos]=i-1;            s.pop();            if(!s.empty())  ff=s.top();            else break;        }    }    if(!s.empty())    {        le[i]=ff.pos+1;        s.push(tmp);    }    else    {        le[i]=1;        s.push(tmp);    }}int main(){   int n,ans_l,ans_r;   LL ans;   while(~scanf("%d",&n))   {        Node tmp;        memset(pre,0,sizeof(pre));        while(!s.empty())  s.pop();        for(int i=1;i<=n;i++)        {            scanf("%d",&tmp.integer);            a[i]=tmp.integer;            if(i==1)  pre[i]=tmp.integer;            else pre[i]=pre[i-1]+tmp.integer;            tmp.pos=i;            solve(tmp);        }        ans=-1;        for(int i=1;i<=n;i++)        {            if(ri[i]==-1)  ri[i]=n;          //  printf("%d %d %d\n",i,le[i],ri[i]);            if(ans<a[i]*(pre[ri[i]]-pre[le[i]-1]))            {                ans=a[i]*(pre[ri[i]]-pre[le[i]-1]);                ans_l=le[i];                ans_r=ri[i];            }        }        printf("%I64d\n",ans);        printf("%d %d\n",ans_l,ans_r);   }   return 0;}
0 0
原创粉丝点击