首页 > 代码库 > 单调栈

单调栈

Largest Rectangle in a Histogram

 POJ - 2559 

用结构体存矩形的宽和高。

如果新来的矩形高小于等于栈顶的矩形,就弹出,并计算更新面积,把栈顶的矩形宽度累加到下一个矩形。

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 #define ll long long
 5 const int maxn=100010;
 6 ll top;
 7 ll ans;
 8 struct Node{
 9     ll h,w;
10 }node;
11 Node s[maxn];
12 int main(){
13     ll n;
14     while(scanf("%lld",&n)&&n){
15             ans=0;
16             top=0;
17         for(int i=0;i<n;i++){
18             ll x;
19             scanf("%lld",&x);
20             node.h=x;
21             node.w=1;
22             ll w=0;
23             while(top&&s[top].h>=x){
24                 Node a=s[top--];
25                 ll temp=a.h*(a.w+w);
26                 w+=a.w;
27                 if(temp>ans) ans=temp;
28             }
29             node.w+=w;
30             s[++top]=node;
31         }
32         ll w=0;
33         while(top){
34             Node a=s[top--];
35             ll temp=a.h*1LL*(a.w+w);
36             w+=a.w;
37             if(ans<temp) ans=temp;
38         }
39         printf("%lld\n",ans);
40     }
41 }
View Code

 

Bad Hair Day

 POJ - 3250 

考虑当前牛能被多少牛看见,维护一个单调递减栈。

技术分享
 1 #include<cstdio>
 2 const int N=80000;
 3 int n,x,s[N],top;
 4 long long ans;
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(int i=1;i<=n;i++)
 9     {
10         scanf("%d",&x);
11         while(top&&s[top]<=x)top--;
12         ans+=top;//栈底从1开始,这样top就是元素,很方便
13         s[++top]=x;
14     }
15     printf("%lld",ans);
16     return 0;
17 }
View Code

 

Feel Good

 POJ - 2796

先从两边各扫一遍找到每一个元素的左边界和右边界,使得它在这个区间内最小。

然后扫一遍更新最大值即可。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 const int maxn=100010;
 6 int a[maxn],L[maxn],R[maxn];
 7 long long s[maxn];
 8 
 9 int main(){
10     int n;
11     scanf("%d",&n);
12     for(int i=1;i<=n;i++){
13         scanf("%d",&a[i]);
14         L[i]=R[i]=i;
15         s[i]=s[i-1]+a[i];
16     }
17     a[0]=a[n+1]=-1;
18     for(int i=1;i<=n;i++){
19         while(a[i]<=a[L[i]-1]) L[i]=L[L[i]-1];
20     }
21     for(int i=n;i>0;i--){
22         while(a[i]<=a[R[i]+1]) R[i]=R[R[i]+1];
23     }
24     long long ans=-1;
25     int l,r;
26     for(int i=1;i<=n;i++){
27         long long temp=(s[R[i]]-s[L[i]-1])*1ll*a[i];
28         if(ans<temp){
29             ans=temp;
30             l=L[i];
31             r=R[i];
32         }
33     }
34     printf("%lld\n%d %d\n",ans,l,r);
35 }
View Code

 

单调栈