【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;
}

全部评论

相关推荐

预计下个星期就能开奖吧,哪位老哥来给个准信
华孝子爱信等:对接人上周说的是这周
点赞 评论 收藏
分享
头像
11-07 01:12
重庆大学 Java
精致的小松鼠人狠话不多:签哪了哥
点赞 评论 收藏
分享
10-25 00:32
香梨想要offer:感觉考研以后好好学 后面能乱杀,目前这简历有点难
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务