今年的Bubble Cup比赛已经结束,有一个问题NEO我没能解决。这个问题要求给定一个包含n个整数元素的数组,将其分成若干部分(可以只有一部分),每一部分都是连续的元素。在这种情况下,NEO值的计算方式为:每一部分的值之和。一部分的值是该部分中所有元素之和乘以其长度。
例如:我们有一个数组:[ 2 3 -2 1 ]。如果我们将其划分为:[2 3] [-2 1]。则NEO = (2 + 3) * 2 + (-2 + 1) * 2 = 10 - 2 = 8。
数组中的元素数量小于
我尝试过类似分治的方法,如果将数组不断分成两部分可以增加最大NEO数字,则执行此操作,否则返回整个数组的NEO。但不幸的是,该算法的最坏情况复杂度为O(N^2)(以下是我的实现),因此我想知道是否有更好的解决方案。
编辑:我的贪心算法不起作用,例如取
例如:我们有一个数组:[ 2 3 -2 1 ]。如果我们将其划分为:[2 3] [-2 1]。则NEO = (2 + 3) * 2 + (-2 + 1) * 2 = 10 - 2 = 8。
数组中的元素数量小于
10^5
,数字是介于-10^6
和10^6
之间的整数。我尝试过类似分治的方法,如果将数组不断分成两部分可以增加最大NEO数字,则执行此操作,否则返回整个数组的NEO。但不幸的是,该算法的最坏情况复杂度为O(N^2)(以下是我的实现),因此我想知道是否有更好的解决方案。
编辑:我的贪心算法不起作用,例如取
[1,2,-6,2,1]
,我的算法返回整个数组,而获取最大NEO值的方法是取[1,2],[-6],[2,1]
部分,从而得到NEO值为(1+2)*2+(-6)+(1+2)*2=6
。#include <iostream>
int maxInterval(long long int suma[],int first,int N)
{
long long int max = -1000000000000000000LL;
long long int curr;
if(first==N) return 0;
int k;
for(int i=first;i<N;i++)
{
if(first>0) curr = (suma[i]-suma[first-1])*(i-first+1)+(suma[N-1]-suma[i])*(N-1-i); // Split the array into elements from [first..i] and [i+1..N-1] store the corresponding NEO value
else curr = suma[i]*(i-first+1)+(suma[N-1]-suma[i])*(N-1-i); // Same excpet that here first = 0 so suma[first-1] doesn't exist
if(curr > max) max = curr,k=i; // find the maximal NEO value for splitting into two parts
}
if(k==N-1) return max; // If the max when we take the whole array then return the NEO value of the whole array
else
{
return maxInterval(suma,first,k+1)+maxInterval(suma,k+1,N); // Split the 2 parts further if needed and return it's sum
}
}
int main() {
int T;
std::cin >> T;
for(int j=0;j<T;j++) // Iterate over all the test cases
{
int N;
long long int NEO[100010]; // Values, could be long int but just to be safe
long long int suma[100010]; // sum[i] = sum of NEO values from NEO[0] to NEO[i]
long long int sum=0;
int k;
std::cin >> N;
for(int i=0;i<N;i++)
{
std::cin >> NEO[i];
sum+=NEO[i];
suma[i] = sum;
}
std::cout << maxInterval(suma,0,N) << std::endl;
}
return 0;
}