题型整理(4) 单调栈 1.视野总和 描述:有n个人站队,所有的人全部向右看,个子高的可以看到个子低的发型,给出每个人的身高,问所有人能看到其他人发现总和是多少。
输入:4 3 7 1 输出:2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int FieldSum (vector<int >& v) { v.push_back (INT_MAX); stack<int > st; int sum = 0 ; for (int i = 0 ; i < (int )v.size (); i++){ if (st.empty () || v[st.top ()] > v[i]) st.push (i); else { while (!st.empty () && v[st.top ()] <= v[i]){ int top = st.top (); st.pop (); sum += (i - top - 1 ); } st.push (i); } } return sum; }
描述:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 , 求在该柱状图中,能够勾勒出来的矩形的最大面积。
输入:2 1 5 6 2 3
输出:10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int maxS (vector<int >& heights) { heights.push_back (0 ); stack<int > stk; int maxs= 0 ; for (int i = 0 ;i<heights.size ();i++){ while (!stk.empty () && heights[i]<heights[stk.top ()]){ int top= stk.top (); stk.pop (); maxs = max (maxs,heights[top]*(stk.empty ()? i:(i - stk.top () -1 ))); } stk.push (i); } return maxs; }
描述:给出一组数字,求一区间,使得区间元素和乘以区间最小值最大,结果要求给出这个最大值和区间的左右端点
输入:3 1 6 4 5 2
输出:60 3 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <stdio.h> #include <iostream> #include <stack> using namespace std;typedef long long LL;int main () { int i,n,pos1,pos2; LL tmp,top,ans,a[100010 ],sum[100010 ]; stack<int > st; while (~scanf ("%d" ,&n)){ while (!st.empty ()) st.pop (); sum[0 ]=0 ; for (i=1 ;i<=n;i++){ scanf ("%lld" ,&a[i]); sum[i]=sum[i-1 ]+a[i]; } a[n+1 ]=-1 ; ans=0 ; for (i=1 ;i<=n+1 ;i++){ if (st.empty ()||a[i]>=a[st.top ()]){ st.push (i); }else { while (!st.empty ()&&a[i]<a[st.top ()]){ top=st.top (); st.pop (); tmp=sum[i-1 ]-sum[top-1 ]; tmp*=a[top]; if (tmp>=ans){ ans=tmp; pos1=top; pos2=i; } } st.push (top); a[top]=a[i]; } } printf ("%lld\n" ,ans); printf ("%d %d\n" ,pos1,pos2-1 ); } return 0 ; }