例题为poj2559,是一道经典例题。
#include<stdio.h>
#include<algorithm>
#include<iostream>
#define MAXN 1000001
using namespace std;
struct squ
{
int height ;
int x ;
}stack[MAXN];
int top;
int main()
{
int n;
int h;
long long ans,tot,tmp;
while(scanf("%d",&n) && n)
{
top = 0;//stack中的个数
ans = 0;//最终的面积, tot为此时最大的面积
for(int i=0; i<n; i++)
{
cin >> h;
tmp = 0;//宽度
while(top > 0 && stack[top-1].height >= h)
{
tot = stack[top-1].height * (stack[top-1].x+tmp);
if( tot > ans) ans = tot;
tmp += stack[top-1].x;
top--;
}
stack[top].height = h;
stack[top].x = 1 + tmp;
top++;
}
tmp = 0;
while( top > 0 )//栈中剩余元素
{
tot = stack[top-1].height * (stack[top-1].x + tmp);
if( tot > ans) ans = tot;
tmp+=stack[top-1].x;
top--;
}
cout << ans << endl;
}
return 0;
}
关于单调栈的一个应用是 求以某一值为最小值的最大区间。
poj3494是在2559的基础上的一道沿生。看了题解才知道怎么做。
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <stack>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn = 2005;
int arr[maxn][maxn];
int sum[maxn][maxn];
int l[maxn],r[maxn];
int main()
{
int m,n;
while(scanf("%d%d",&m,&n) == 2)
{
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
scanf("%d",&arr[i][j]);
memset(sum,0,sizeof(sum));
for(int j=1; j<=n; j++)
for(int i=1; i<=m; i++)
{
if(arr[i][j] == 1)
sum[i][j] = sum[i-1][j] + 1;
else
sum[i][j] = 0;
}
for(int i=1; i<=m; i++)
sum[i][0] = sum[i][n+1] = -1;
int ans = 0;
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
l[j] = r[j] = j;
for(int j=1; j<=n; j++)
while(sum[i][l[j]-1] >= sum[i][j])
l[j] = l[l[j]-1];
for(int j=n; j>=1; j--)
while(sum[i][r[j]+1] >= sum[i][j])
r[j] = r[r[j]+1];
for(int j=1; j<=n; j++)
ans = max(ans,sum[i][j]*(r[j]-l[j]+1));
}
printf("%d\n",ans);
}
}