Original Problem: Problem 1(INOI 2015)
有两个数组A[1..N]
和B[1..N]
操作SSum
在其上定义为
SSum[i,j]
时,A[i] + A[j] + B[t (where t = i+1, i+2, ..., j-1)]
= i < j
当SSum[i,j]
A[i] + A[j] + B[t (where t = 1, 2, ..., j-1, i+1, i+2, ..., N)]
= i > j
SSum[i,i]
= A[i]
挑战在于找到SSum的最大可能值。
我有一个基于计算B
#include <iostream>
#include <utility>
int main(){
int N;
std::cin >> N;
int *a = new int[N+1];
long long int *bPrefixSums = new long long int[N+1];
for (int iii=1; iii<=N; iii++) //1-based arrays to prevent confusion
std::cin >> a[iii];
bPrefixSums[0] = 0;
for (int b,iii=1; iii<=N; iii++){
std::cin >> b;
bPrefixSums[iii] = bPrefixSums[iii-1] + b;
}
long long int SSum, SSumMax=-(1<<10);
for (int i=1; i <= N; i++)
for (int j=1; j <= N; j++){
if (i<j)
SSum = a[i] + a[j] + (bPrefixSums[j-1] - bPrefixSums[i]);
else if (i==j)
SSum = a[i];
else
SSum = a[i] + a[j] + ((bPrefixSums[N] - bPrefixSums[i]) + bPrefixSums[j-1]);
SSumMax = std::max(SSum, SSumMax);
}
std::cout << SSumMax;
return 0;
}
对于大约10 ^ 6的较大N值,程序无法在3秒内完成任务。
答案 0 :(得分:1)
由于我没有足够的代表来添加评论,我将在这个答案中写下这些想法。
这个问题非常好,我实际上受到了link的启发。感谢@superty。
我们可能会单独考虑此问题,换句话说,分为三个条件:i == j
,i < j
,i > j
。我们只需要找到最大的结果。
考虑i == j
:最大结果应为a [i],并且很容易在O(n)时间复杂度中找到答案。
考虑i < j
:它与经典的最大和问题非常相似,并且对于每个j
,我们只需要找到左边的i
设法制作结果最大。
首先考虑经典问题,如果要求我们得到数组a的最大部分和,我们计算a的前缀和,以获得O(n)复杂度。现在在这个问题上,它几乎是一样的。
您可以在此处看到(i < j
),我们有SSum[i,j] = A[i] + A[j] + B[t (where t = i+1, i+2, ..., j-1)] = (B[1] + B[2] + ... + B[j - 1] + A[j]) - (B[1] + B[2] + ... B[i] - A[i])
,当j
保持不变时第一个词保持不变,而i
保持不变时第一个词保持不变1}}保持不变。所以现在的解决方案非常明确,你得到两个前缀和&#39;并为每个prefix_sum_2[i]
找到最小的prefix_sum_1[j]
。
考虑i > j
:它与SO上的discussion非常相似(但这个讨论并没有多大帮助)。
同样,我们得到SSum[i,j] = A[i] + A[j] + B[t (where t = 1, 2, ..., j-1, i+1, i+2, ..., N)] = (B[1] + B[2] + ... + B[j - 1] + A[j]) + (A[i] + B[i + 1] + ... + B[n - 1] + B[n])
。现在你需要得到数组的prefix-sum和suffix-sum(我们需要prefix_sum[i] = a[i] + prefix_sum[i - 1] - a[i - 1]
和后缀类似),并获得另外两个数组,比如ans_left[i]
为the maximum value of the first term for all j <= i
和ans_right[j]
为the maximum value of the second term for i >= j
,因此此条件下的答案是所有(ans_left[i] + ans_right[i + 1])
最后,原始问题所需的最大结果是这三个子案例的答案的最大值。
很清楚地看到总复杂度是O(n)。