CSP/NOIP 复习:单调栈

最近模拟赛打的都不是太好,先随便复习复习吧,马上就要 CSPS 了,我可以考好的。

这里放一些单调栈的题目,笛卡尔树先不说,这个我已经忘了,后天复习一下。

本体

栈中维护有单调性的数据,入栈时维护这个单调性,这是计算结果。

是个人都会,不想多写。

直接进入 dlc 环节。

最大子矩形。

就是一个平面,有一些障碍不能选,要求我们选出来一个最大的,不包含障碍的子矩形,这个就可以使用单调栈来做。

我们先考虑一个弱化版的。

HISTOGRA - Largest Rectangle in a Histogram

这个是简单的,我们考虑尽可能使用每个位置的最高值,也就是算出来左边最近的比它矮的位置和右边最近比它矮的位置。

正确性显然,最大的矩形肯定尽可能用完了位置。

直接上单调栈,注意初始化左右要大一个。

代码↓

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=1e6+116;
bool ed=false;
int stk[MN], top, n, a[MN];
int l[MN], r[MN], ans=0;
void Getl(){
	top=0;
	for(int i=1; i<=n; ++i){
		while(top&&a[stk[top]]>a[i]){
			r[stk[top]]=i; --top;
		}
		stk[++top]=i;
	}
}
void Getr(){
	top=0;
	for(int i=n; i>=1; --i){
		while(top&&a[stk[top]]>a[i]){
			l[stk[top]]=i; --top;
		}
		stk[++top]=i;
	}
}
void Solve(){
	cin>>n; for(int i=1; i<=n; ++i) cin>>a[i];
	if(n==0){ed=true; return;}
	for(int i=1; i<=n; ++i) l[i]=0;
	for(int i=1; i<=n; ++i) r[i]=n+1;
	Getl(); Getr(); ans=0;
	for(int i=1; i<=n; ++i){
		ans=max(ans,(r[i]-l[i]-1)*a[i]);
	}
	cout<<ans<<'\n';
}
signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	while(!ed) Solve();
	return 0;
}

换到二维上就很简单了,对于每一个高度跑一遍就行了。

P4147 玉蟾宫

代码↓

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=3145;
char mp[MN][MN];
int n, m, h[MN][MN];
int stk[MN], top=0;
int l[MN], r[MN], ans=0;
void Read(){
	cin>>n>>m;
	for(int i=1; i<=n; ++i){
		for(int j=1; j<=m; ++j){
			cin>>mp[i][j];
		}
	}
	for(int i=1; i<=n; ++i){
		for(int j=m; j>=1; --j){
			h[i][j]=h[i][j+1]+1;
			if(mp[i][j]=='R') h[i][j]=0;
		}
	}
}
void Getr(int height){
	top=0;
	for(int i=1; i<=n; ++i) r[i]=n+1;
	for(int i=1; i<=n; ++i){
		while(top&&h[stk[top]][height]>h[i][height]){
			r[stk[top]]=i; --top;
		}
		stk[++top]=i;
	}
}
void Getl(int height){
	top=0;
	for(int i=1; i<=n; ++i) l[i]=0;
	for(int i=n; i>=1; --i){
		while(top&&h[stk[top]][height]>h[i][height]){
			l[stk[top]]=i; --top;
		}
		stk[++top]=i;
	}
}
void Solve(){
	Read();
	for(int height=1; height<=m; ++height){
		Getl(height); Getr(height);
		for(int i=1; i<=n; ++i){
			//cout<<l[i]<<" "<<r[i]<<" | ";
			ans=max(ans,(r[i]-l[i]-1)*(h[i][height]));
		}
	}
	cout<<ans*3<<'\n';
}
signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	Solve();
	return 0;
}
posted @ 2025-10-24 19:20  BaiBaiShaFeng  阅读(5)  评论(0)    收藏  举报
Sakana Widget右下角定位