F-Square, Not Rectangle Gym-102760F (Valor mínimo del mantenimiento del intervalo de la tabla ST + dos puntos)

Un histograma es un polígono formado al alinear N rectángulos adyacentes que comparten una línea de base común. Cada rectángulo se llama barra. La i-ésima barra de la izquierda tiene un ancho 1 y una altura Hi.

Tu objetivo es encontrar el área del rectángulo más grande contenido en el histograma dado, de modo que uno de los lados sea paralelo a la línea base.

Figura 1. El histograma dado en el ejemplo, con el rectángulo más grande mostrado a la derecha.

En realidad, no, tienes que encontrar el cuadrado más grande. Dado que el área de un cuadrado está determinada por la longitud de su lado, debe generar la longitud del lado en lugar del área.

Figura 2. El histograma dado en el ejemplo, con el cuadrado más grande mostrado a la derecha.

Entrada
En la primera línea, se da un único entero N, donde 1≤N≤300000.

En la siguiente línea, se dan N números enteros separados por espacios H1, H2, ⋯, HN. Hi (1≤Hi≤109) es la altura de la i-ésima barra.

Salida
Muestra la longitud del lado del cuadrado más grande del histograma, de modo que uno de los lados sea paralelo a la línea base.

Ejemplo
Entrada
6
3 4 4 4 4 3
Salida
4

Idea: El problema es encontrar el cuadrado con el área más grande. Encuentre el área más grande del cuadrado en un intervalo. El área debe depender del valor mínimo en el intervalo. Debido a que es una operación fuera de línea, pensé que La tabla ST puede mantener el valor mínimo para resolverlo, pero debido a la cantidad de datos Por la razón, puede elegir la dicotomía para acelerar el intervalo de bloqueo para ayudar en la solución.

Código 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;
}

Supongo que te gusta

Origin blog.csdn.net/qq_40924271/article/details/111411716
Recomendado
Clasificación