F - Square, Not Rectangle Gym - 102760F(ST表区间维护最小值+二分)

A histogram is a polygon made by aligning N adjacent rectangles that share a common base line. Each rectangle is called a bar. The i-th bar from the left has width 1 and height Hi.

Your goal is to find the area of the largest rectangle contained in the given histogram, such that one of the sides is parallel to the base line.

Figure 1. The histogram given in the example, with the largest rectangle shown on the right.

Actually, no, you have to find the largest square. Since the area of a square is determined by its side length, you are required to output the side length instead of the area.

Figure 2. The histogram given in the example, with the largest square shown on the right.

Input
On the first line, a single integer N is given, where 1≤N≤300000.

On the next line, N space-separated integers H1,H2,⋯,HN, are given. Hi (1≤Hi≤109) is the height of the i-th bar.

Output
Output the side length of the largest square in the histogram, such that one of the sides is parallel to the base line.

Example
Input
6
3 4 4 4 4 3
Output
4

思路:问题是寻找最大面积的正方形,一个区间内寻找正方形的最大面积,面积肯定取决于区间内的最小值大小,由于是离线操作,于是想到了可以ST表维护最小值求解,但由于数据量的原因,可以选择二分来加快锁定区间的速度辅助求解。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug(a) cout<<#a<<"="<<a<<endl;
#define speed {
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
#define ll long long
#define int long long
using namespace std;
const double PI = acos(-1.0);
const int maxn = 1e6+ 10;
const int inf = 0x3f3f3f3f;
const ll INF = 1ll << 62;
const double eps_0 = 1e-8;
const int mod = 1e9 + 7;
ll gcd(ll x, ll y) {
    
    
	return y ? gcd(y, x % y) : x;
}
ll lcm(ll x, ll y) {
    
    
	return x * y / gcd(x, y);
}
inline int rd() {
    
    
	int x = 0, f = 1;
	char ch = getchar();
	while (ch<'0' || ch>'9') {
    
    
		if (ch == '-')f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
    
    
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
int Log[maxn], a[maxn], st[maxn][25];//st表
int n;
void init() {
    
    //维护区间最小值,最大值同理
	Log[1] = 0;
	for (int i = 2; i <= n + 1; ++i)Log[i] = Log[i / 2] + 1;
	for (int i = 1; i <= n; ++i)st[i][0] = a[i];
	for (int j = 1; (1 << j) <= n; ++j) {
    
    
		for (int i = 1; i + (1 << (j - 1)) <= n; ++i) {
    
    
			st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
		}
	}
	//输出表
	//for (int j = 1; (1 << j) <= n; ++j) {
    
    
	//	for (int i = 1; i + (1 << (j - 1)) <= n; ++i) {
    
    
	//		printf("%lld ", st[i][j]);
	//	}
	//	cout << endl;
	//}
}
int query(int l, int r) {
    
    //查询最小值,最大值同理
	int k = Log[r - l + 1];
	int ans = min(st[l][k], st[r - (1 << k) + 1][k]);
	return ans;
}
int judge(int x) {
    
    
	for (int i = 1; i <= n - x + 1; i++) {
    
    
		if (query(i, i + x - 1) >= x)return 1;
	}
	return 0;
}
signed main() {
    
    
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)scanf("%lld", &a[i]);
	init();
	int l = 1;
	int r = n;
	int mid;
	int res = -1;
	while (r >= l) {
    
    
		mid = (l + r) >> 1;
		if (judge(mid)) {
    
    
			if (mid > res)res = mid;
			l = mid + 1;
		}
		else {
    
    
			r = mid - 1;
		}
	}
	printf("%lld\n", res);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40924271/article/details/111411716