時間限制: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個數,求所有連續區間中區間和*區間最小值的最大值。
思路:
由於每個數的範圍很小,我們可以枚舉每一個數字,假設它是所在區間中的最小數,然後看它最左最右的範圍。
預處理一下區間和,然後搞一下區間範圍,然後枚舉答案。。。
*/