首页 > 代码库 > 51Nod - 1102 面积最大的矩形

51Nod - 1102 面积最大的矩形

51Nod - 1102 面积最大的矩形

有一个正整数的数组,化为直方图,求此直方图包含的最大矩形面积。例如 2,1,5,6,2,3,对应的直方图如下:
 
技术分享
 
面积最大的矩形为5,6组成的宽度为2的矩形,面积为10。
 
Input
第1行:1个数N,表示数组的长度(0 <= N <= 50000)
第2 - N + 1行:数组元素A[i]。(1 <= A[i] <= 10^9)
Output
输出最大的矩形面积
Input示例
6
2
1
5
6
2
3
Output示例
10

 

题解: 

    (1), 第一种方法使用 rmq 的方法,建立线段树sparse table,然后再搜两端点找到最小值,扩充为该端点与之最小值的乘积。可是只ac了60%。 

    (2), 第二种方法是采用经典的 left_array 和 right_array 两个数组,找到每一个数组元素可以扩展到的最大值。 

 

 

#include <iostream>
#include <cstdio> 
#include <cstring> 
#include <algorithm>
#include <cmath>  
using namespace std; 
const int MAXN = 50000 + 10; 
int n, m, num[MAXN], dp[MAXN][30], dp_p[MAXN][30]; 
long long ans; 

void build(){
	for(int i=0; i<n; ++i){
		dp[i][0] = num[i]; 
		dp_p[i][0] = i; 
	} 
	for(int i=1; (1<<i)<=n; ++i){
		for(int j=0; j+(1<<i)-1< n; ++j){
			if(dp[j][i-1] > dp[j+(1<<(i-1))][i-1]){
				dp[j][i] = dp[j+(1<<(i-1))][i-1]; 
				dp_p[j][i] = dp_p[j+(1<<(i-1))][i-1]; 
			}else{
				dp[j][i] = dp[j][i-1]; 
				dp_p[j][i] = dp_p[j][i-1]; 
			}
		}
	}
}

void Search(int l, int r){
	if(l >= r){ 
		return; 
	}
	int minv, min_j, k = (int)(log2(1.0*(r - l + 1))); 
	if(dp[l][k] < dp[r-(1<<k)+1][k]){
		minv = dp[l][k]; 
		min_j = dp_p[l][k]; 
	}else{
		minv = dp[r-(1<<k) + 1][k]; 
		min_j = dp_p[r-(1<<k) + 1][k]; 
	} 
	if(ans < (long long)(minv*(r - l + 1))){
		ans = (long long)(minv * (r-l + 1)); 
	}
	Search(l, min_j - 1); 
	Search(min_j + 1, r); 
}

int main(){
	freopen("in.txt", "r", stdin); 

	while(scanf("%d", &n) != EOF){
		ans = 0; 
		for(int i=0; i<n; ++i){
			scanf("%d", &num[i]); 
			ans = max(ans, (long long)(num[i])); 
		} 
		build(); 
		Search(0, n-1); 
		printf("%lld\n", ans );
	} 
	return 0; 
}

  

 

 

 

 

#include <iostream>
#include <cstdio> 
#include <cstring> 
#include <algorithm>
#include <cmath>  
using namespace std; 
const int MAXN = 50000 + 10; 

long long ans, num[MAXN], l[MAXN], r[MAXN];  

int main(){

	int n, k, i; 
	scanf("%d", &n); 
	for(i=1; i<=n; ++i){
		scanf("%lld", &num[i]); 
	}
	num[0] = num[n+1] = 0; 
	for(i=1; i<=n; ++i){
		k = i - 1;
		while(num[i] <= num[k]){
			k = l[k] - 1; 
		}
		l[i] = k + 1; 
	}
	for(i=n; i>=1; --i){
		k = i + 1; 
		while(num[i] <= num[k]){
			k = r[k] + 1; 
		}
		r[i] = k - 1; 
	}
	ans = 0; 
	for(i=1; i<=n; ++i){
		if(ans < num[i]*(r[i] - l[i] + 1)){
			ans = num[i]*(r[i] - l[i] + 1); 
		}
	}
	printf("%lld\n",  ans); 
	return 0; 
}

  

 

51Nod - 1102 面积最大的矩形