【CCF 201312-3】最大的矩形(单调栈) & 【POJ 2823】Sliding Window(单调队列) Apare_xzc
最大的矩形(单调栈) & Sliding Window(单调队列)
今天刷CCF的时候碰到了最大的矩形这个题,顺便复习了一下单调栈和单调队列
Sliding Window
POJ 2823题目链接<–
题意:
给一个1E6长的数列,求每个长度为K的区间的最大值和最小值
代码:
/* POJ 2823 Sliding Window Run ID User Problem Result Memory Time Language Code Length Submit Time 21072853 apare 2823 Accepted 4016K 5516MS C++ 1249B 2019-11-20 14:03:59 21072236 apare 2823 Time Limit Exceeded C++ 823B 2019-11-20 11:26:56 单调队列,用deque TLE了,用数组模拟队列,5516MS过了 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
//#include <deque>
using namespace std;
const int maxn = 1e6+100;
int a[maxn];
int Q[maxn];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
{
scanf("%d",a+i);
}
/* deque<pair<int,int> >Q; //pair<value,pos> for(int i=1;i<=n;++i) { while(!Q.empty()&&a[i]<=Q.back().first) Q.pop_back(); Q.push_back(make_pair(a[i],i)); while(!Q.empty()&&Q.front().second<=Q.back().second-k) Q.pop_front(); if(i>=k) printf("%d%c",Q.front().first,i==n?'\n':' '); } Q.clear(); for(int i=1;i<=n;++i) { while(!Q.empty()&&a[i]>=Q.back().first) Q.pop_back(); Q.push_back(make_pair(a[i],i)); while(!Q.empty()&&Q.front().second<=Q.back().second-k) Q.pop_front(); if(i>=k) printf("%d%c",Q.front().first,i==n?'\n':' '); } return 0; */
int pf = 0,pb = 0;
for(int i=1;i<=n;++i)
{
while(pb>pf&&a[i]<=a[Q[pb-1]]) pb--;
Q[pb++] = i;
while(pb>pf&&Q[pf]<=Q[pb-1]-k) pf++;
if(i>=k) printf("%d%c",a[Q[pf]],i==n?'\n':' ');
}
pf = pb = 0;
for(int i=1;i<=n;++i)
{
while(pb>pf&&a[i]>=a[Q[pb-1]]) pb--;
Q[pb++] = i;
while(pb>pf&&Q[pf]<=Q[pb-1]-k) pf++;
if(i>=k) printf("%d%c",a[Q[pf]],i==n?'\n':' ');
}
return 0;
}
最大的矩形
题意:求最大的矩形的面积
思路:
- 求最大的矩形的面积,那么求高度为h[1],h[2],h[3]…到h[n]的最大的矩形面积的最大值
- 那么我们要做的就是处理出每个高度h[i]左边和右边能拓展的长度(找到左右两边最远的高度>=h[i]的坐标L[i]和R[i])
- 那么ans = max(ans, h[i]*(R[i]-L[i]+1))
- 可以用单调栈维护:
先把0入栈,然后从做到右和从右到左分别维护单调递增的栈
pos 0 1 2 3 4 5 6
height 0 3 1 6 5 2 4
0
0 3(0个)
0 1(1个)
0 1 6
0 1 5
0 1 2
0 1 2 4
代码
#include <bits/stdc++.h>
using namespace std;
int a[1005],L[1005],R[1005];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",a+i);
stack<pair<int,int> > st; //pair(value,pos)
st.push(make_pair(0,0));
for(int i=1;i<=n;++i)
{
while(!st.empty()&&st.top().first>=a[i]) st.pop();
L[i] = st.top().second+1;
st.push(make_pair(a[i],i));
}
while(!st.empty()) st.pop();
st.push(make_pair(0,n+1));
for(int i=n;i>=1;--i)
{
while(!st.empty()&&st.top().first>=a[i]) st.pop();
R[i] = st.top().second-1;
st.push(make_pair(a[i],i));
}
int ans = 0;
for(int i=1;i<=n;++i)
ans = max(ans,a[i]*(R[i]-L[i]+1));
printf("%d\n",ans);
return 0;
}