标签:
通过一个例子,简要证明一下单调栈 。 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; }
标签:
原文地址:http://blog.csdn.net/u014303647/article/details/45649801