B4273 [蓝桥杯青少年组省赛 2023] 最大的矩形纸片

B4273 [蓝桥杯青少年组省赛 2023] 最大的矩形纸片

大意

直方图中的最大矩形

思路

首先这个题目要求的是长直图中最大的矩形,我们考虑用笛卡尔树去完成这个题目。

首先我们以高度为点权建立笛卡尔树,然后我们如果知道一个点有多少个子节点,那么这个点的矩形并的答案为 \(h[i] * sz[i]\),最后全部跑一次即可。

当然,朴素的单调栈也未尝不可,但是笛卡尔树更加形象。

代码

#include<iostream>
#include<stack>
using namespace std;

#define int long long
const int MAXN = 1e6 + 10;

int n, a[MAXN];
int l[MAXN], r[MAXN];
int sz[MAXN], in[MAXN], ans;
stack<int> st;

int dfs(int x){
	sz[x] = 1;
	if(l[x]) sz[x] += dfs(l[x]);
	if(r[x]) sz[x] += dfs(r[x]);
	return sz[x];
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n;
	for(int i = 1;i <= n;i ++){
		cin >> a[i];
	}
	st.push(1);
	for(int i = 2;i <= n;i ++){
		int lst = st.top();
		while(!st.empty() && a[i] < a[st.top()]){
			lst = st.top();
			st.pop();
		}
		if(st.empty()){
			l[i] = lst;
		}
		else{
			l[i] = r[st.top()];
			r[st.top()] = i;
		}
		st.push(i);
		in[l[i]] ++;
		in[r[i]] ++;
	}
	for(int i = 1;i <= n;i ++){
		if(!in[i]){
			int c = dfs(i);
		}
	}
	int ans = 0;
	for(int i = 1;i <= n;i ++){
		ans = max(ans, a[i] * sz[i]);
	}
	cout << ans << '\n';
	return 0;
}
posted @ 2026-01-24 09:04  To_Carpe_Diem  阅读(0)  评论(0)    收藏  举报