最大化数组总和

Maximize array sum

本文关键字:数组 最大化      更新时间:2023-10-16

假设我给出了一个大小的整数数组 n.It 给定我们可以在一个操作中将 (i( th 和 (i+1( 元素的值乘以 -1。我们可以根据需要多次执行此操作。我们的目标是最大化 eintire 数组的总和。并打印该总和。

约束:

2<=n<=10^5

-10^9 <=a(i( <= 10^9

我的代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,a,i;
cin >> n;
vector<int>v1;
for(i=0;i<n;i++)
{
cin >> a;
v1.push_back(a);
}
for(i=0;i<n-1;)
{
if(v1[i]<0 && v1[i+1]<0)
{
v1[i]=v1[i]*(-1);
v1[i+1]=v1[i+1]*(-1);
i=i+2;
}
else
{
i++;
}
}
long long int sum=0;
for(i=0;i<n-1;i++)
{
if(v1[i]<0 && abs(v1[i])>abs(v1[i+1]))
{
v1[i]=v1[i]*(-1);
v1[i+1]=v1[i+1]*(-1);
}
}
for(i=0;i<n;i++)
{
//  cout <<v1[i] << " ";
}
for(i=0;i<n;i++)
{
sum=sum+v1[i];
}
cout << sum;
}

我的代码被某些测试用例接受。谁能帮我找出这个问题的正确逻辑?

好吧,只需考虑所有情况:

  • 案例++-->我们得到--
  • 案例---->我们得到++
  • 案例-+-->我们得到+-
  • 案例+--->我们得到-+

我们可以注意到,如果我们试图使所有元素都成为正数,我们最终最多会得到一个负元素。

同样通过案例3和4,我们可以看到我们可以决定哪个元素(如果有的话(最终将是负的。

所以结果只是数组的绝对值之和减去数组中的最小绝对值(如果负元素的数量最初是奇数(

首先,你需要明白,在这个竞争激烈的问题中,你永远无法学到C++。相反,你的C++会变得更糟。

接下来,在所有这些问题中,作者通过在约束中提供大量数字,已经给了你一个强有力的提示。这是一个强烈的信息。不要使用暴力破解方法开始编码。想出一个智能解决方案。

先想,再想一想,再做最后的思考,开发一个好的算法。

任务是,使尽可能多的值为正。

有了手头的问题,您将看到您可以通过将给定的操作应用于您想要的任何位置来移动负号。示例:让字母为正整数。然后你可以变形:

a -b  c  d   to   
-a  b  c  d   or to
a  b -c  d   or to
a  b -c  d and then a  b  c  -d

这应该被理解。

如果您有偶数个负数,则可以通过将负号移动到另一个负数下方来限制其中的 2 个负数,然后将两个值都设为正数。此机制也适用于数组中较负偶数。

第一个结论:具有偶数个负数的数组与所有数字均为正数的数组相同。我们可以将所有绝对值相加并得到结果。

如果我们有奇数个负数,我们可以将符号移动到我们想要的任何位置,并且可以消除除负值之外的所有符号。因为总和必须是最大值,所以负值必须是最小的,因为它将被替换。因此,首先,我们尽可能多地消除负数,然后将负号移至最小的绝对值。

现在我们进一步思考:

我们需要找出负值的计数。如果它是偶数,我们可以简单地将所有值的绝对值相加并得到结果。对于奇数值,我们需要找到最小的绝对值并减去它。

我们可以有一个想法,读取std::vector中的所有值,然后计数,计算等等。但不需要。我们已经可以在读取输入期间执行此操作。我们检查到目前为止的最小值,看看负数的总计数是奇数还是偶数。我们在读取过程中对所有绝对值求和。如果我们最后知道这个数字是奇数,那么我们将最小的数字减去两次(因为我们已经添加了它(。

然后,程序可能如下所示:

#include <iostream>
#include <cmath>
#include <limits>
int main() {
// Get the number of test values
size_t numberOfTestValues{};
std::cin >> numberOfTestValues;
// Here we will indicate, if the number of negatives is odd or even
bool oddNumberOfSignedValues{ false };
// This will be the result, the running sum
long sum{};
// This is the smallest value given
long smallestValue{std::numeric_limits<long>::max()};
// Read as many values as specified
for (size_t i{}; i < numberOfTestValues; ++i) {
// Read the vale
long value{};
std::cin >> value;
// Check, if we have now, at this moment, an odd or even number of negatives
if (value < 0)  oddNumberOfSignedValues = not oddNumberOfSignedValues;
value = std::abs(value);
// Check for a new smallest value
if (value < smallestValue) smallestValue = value;
// Accumulate
sum += value;
}
// In case necessary (count of negatives was odd) subtract smallest number
if (oddNumberOfSignedValues) sum = sum - smallestValue - smallestValue;
// Show result to use
std::cout << sum << 'n';
return 0;
}

这将导致最小的复杂性。