今日頭條2018校招算法方向(第一批)編程題2(枚舉)

時間限制:3秒

空間限制:131072K

給定一個數組序列, 需要求選出一個區間, 使得該區間是所有區間中經過如下計算的值最大的一個:

區間中的最小數 * 區間所有數的和最後程序輸出經過計算後的最大值即可,不需要輸出具體的區間。如給定序列  [6 2 1]則根據上述公式, 可得到所有可以選定各個區間的計算值:

 

[6] = 6 * 6 = 36;

[2] = 2 * 2 = 4;

[1] = 1 * 1 = 1;

[6,2] = 2 * 8 = 16;

[2,1] = 1 * 3 = 3;

[6, 2, 1] = 1 * 9 = 9;

 

從上述計算可見選定區間 [6] ,計算值爲 36, 則程序輸出爲 36。

區間內的所有數字都在[0, 100]的範圍內;


輸入描述:
第一行輸入數組序列長度n,第二行輸入數組序列。
對於 50%的數據,  1 <= n <= 10000;
對於 100%的數據, 1 <= n <= 500000;


輸出描述:
輸出數組經過計算後的最大值。

輸入例子1:
3
6 2 1

輸出例子1:
36
#include <bits/stdc++.h>
using namespace std;
int a[500005], pre[500005], l[500005], r[500005];
int main(){
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%d", &a[i]);
	}
	pre[0] = 0;
	for(int i = 1; i <= n; ++i){
		pre[i] = pre[i - 1] + a[i];
	}
	int L, R;
	for(int i = 1; i <= 100; ++i){
		L = 1;
		for(int j = 1; j <= n; ++j){
			if(a[j] < i){
				L = j + 1;
			}
			if(a[j] == i){
				l[j] = L;
			}
		}
	}
	for(int i = 1; i <= 100; ++i){
		R = n;
		for(int j = n; j >= 1; --j){
			if(a[j] < i){
				R = j - 1;
			}
			if(a[j] == i){
				r[j] = R;
			}
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i){
		ans = max(ans, (pre[r[i]] - pre[l[i] - 1]) * a[i]);
	}
	cout << ans << endl;
	
}

/*
題意:
5e5個數,求所有連續區間中區間和*區間最小值的最大值。

思路:
由於每個數的範圍很小,我們可以枚舉每一個數字,假設它是所在區間中的最小數,然後看它最左最右的範圍。
預處理一下區間和,然後搞一下區間範圍,然後枚舉答案。。。
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章