题意:给定一个序列,求一串连续子序列,使得连续子序列的和*连续子序列最小值最大。
分析:这题只能用前缀和和区间最小值来解决了,就要看以什么为搜索对象。
以最小值为搜索对象,搜索一个最大区间,使得区间里的数都大于这个最小值。
for (int i = 1; i <= n; i++) {
while (A[i] <= A[L[i] - 1])L[i] =L[L[i] - 1];//更新最左区间,使得区间里的数小于A[i],有一点动态规划
}
for (int i = n; i >= 1; i--) {
while (A[i] <= A[R[i] + 1])R[i] = R[R[i] + 1];
}
然后直接遍历一遍就好了。
#include<iostream>
#include<string.h>
#include<sstream>
#include<set>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<math.h>
using namespace std;
const int maxn = 100000 + 10;
int main() {
int n;
int A[maxn];
int L[maxn], R[maxn];
long long sum[maxn];
sum[0] = 0;
int flag = 0;
while (cin >> n && n) {
for (int i = 1; i <= n; i++) {
cin >> A[i]; L[i] = i, R[i] = i; sum[i] = sum[i - 1] + A[i];
}
A[0] = -1, A[n + 1] = -1;
for (int i = 1; i <= n; i++) {
while (A[i] <= A[L[i] - 1])L[i] =L[L[i] - 1];//更新最左区间,使得区间里的数小于A[i],有一点动态规划
}
for (int i = n; i >= 1; i--) {
while (A[i] <= A[R[i] + 1])R[i] = R[R[i] + 1];
}
long long maxv = (long long)A[1] * A[1];
int r = 1, l = 1;
for (int i = 1; i <= n; i++) {
long long cur = (sum[R[i]] - sum[L[i] - 1])*A[i];
if (cur > maxv || (cur == maxv && (R[i] - L[i]) < (r - l))) {
maxv = cur;
r = R[i]; l = L[i];
}
}
if (flag++)cout << endl;
cout << maxv << endl << l << " " << r << endl;
}
return 0;
}