トップページに戻る
次の競技プログラミングの問題へ
前の競技プログラミングの問題へ
ABC-125-D Flipping Signs
■■■問題■■■
N個の整数が並んでおり、順に A1,A2, ・・・ , ANです。
あなたは、この整数列に対して次の操作を好きなだけ行うことができます。
操作: 1 <= i <= N - 1を満たす整数iを選ぶ。AiとAi+1 に -1を乗算する。
操作終了後の整数列を B1 , B2 , ・・・ , BNとします。
B1 + B2 + ・・・ + BN の最大値を求めてください。
■■■入力■■■
N
A1 A2 ・・・ AN
●入力は全て整数である
●2 <= N <= 10万
●-10億 <= Ai <= 10億
■■■出力■■■
B1 + B2 + ・・・ + BN の最大値を出力せよ。
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("3");
WillReturn.Add("-10 5 -4");
//19
//次のように操作を行うと、B1=10 , B2=5 , B3=4 になり、
//このときの B1+B2+B3 = 10+5+4 = 19 が最大です。
//●iとして1を選ぶ。操作により、整数列は 10,-5,-4に変化する。
//●iとして2を選ぶ。操作により、整数列は 10,5,4に変化する。
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("10 -4 -8 -11 3");
//30
}
else if (InputPattern == "Input3") {
WillReturn.Add("11");
WillReturn.Add("-1000000000 1000000000 -1000000000 1000000000 -1000000000 0 1000000000 -1000000000 1000000000 -1000000000 1000000000");
//10000000000
//出力が32ビット整数型に収まらない場合があります
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
int[] AArr = InputList[1].Split(' ').Select(X => int.Parse(X)).ToArray();
//負数の数
int MinusCnt = AArr.Count(X => X < 0);
//絶対値の最小値
int MinABS = AArr.Min(X => Math.Abs(X));
long SumABS = 0;
Array.ForEach(AArr, X => SumABS += Math.Abs(X));
//負数が偶数個の場合
if (MinusCnt % 2 == 0) {
Console.WriteLine(SumABS);
}
else { //負数が奇数個の場合
Console.WriteLine(SumABS - MinABS * 2);
}
}
}
解説
下記の考察をふまえて、負数の個数で場合分けしてます。
●負数が偶数個なら、全ての符号をプラスにするのが最善。
●負数が奇数個なら、絶対値が最小の数値をマイナスにするのが最善。