1. 程式人生 > >51Nod - 1102 面積最大的矩形

51Nod - 1102 面積最大的矩形

array ear true 矩形 tps clu n-1 ios tex

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 面積最大的矩形