AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC182-D Wandering
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("2 -1 -2");
//5
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("-2 1 3 -1 -1");
//2
}
else if (InputPattern == "Input3") {
WillReturn.Add("5");
WillReturn.Add("-1000 -1000 -1000 -1000 -1000");
//0
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] AArr = InputList[1].Split(' ').Select(pX => long.Parse(pX)).ToArray();
long UB = AArr.GetUpperBound(0);
// 累積和の配列
long[] RunSumArr = (long[])AArr.Clone();
for (int I = 1; I <= UB; I++) {
RunSumArr[I] += RunSumArr[I - 1];
}
// 動作を終えた時の、座標位置の配列
long[] StaPosArr = new long[UB + 1];
StaPosArr[0] = 0;
for (int I = 1; I <= UB; I++) {
StaPosArr[I] += StaPosArr[I - 1];
StaPosArr[I] += RunSumArr[I - 1];
}
// 累積和の配列の、累積Maxの配列
long[] RunMaxArr = new long[UB + 1];
RunMaxArr[0] = RunSumArr[0];
for (int I = 1; I <= UB; I++) {
RunMaxArr[I] = Math.Max(RunMaxArr[I - 1], RunSumArr[I]);
}
long Answer = 0;
for (int I = 0; I <= UB; I++) {
Answer = Math.Max(Answer, StaPosArr[I] + RunMaxArr[I]);
}
Console.WriteLine(Answer);
}
}
解説
ナイーブにシュミレーションすると、O(N*N)でTLEなので
サンプル2で考察すると、
-2
-2 1
-2 1 3
-2 1 3 -1
-2 1 3 -1 -1
といった動作を行うことが分かります。
-2 1 3 -1 -1 の累積和は
-2 -1 2 1 0 になり、
この配列から、動作を終えた時の、座標位置を求め、
上の図の左端に追記すると、下記になります。
0 | -2
-2 | -2 1
-3 | -2 1 3
-1 | -2 1 3 -1
0 | -2 1 3 -1 -1
後は、上記の累積和から累積Maxを求めると
-2 -1 2 2 2 なので、
動作を終えた時の、
座標位置ごとに累積Maxを足した値の最大値が、解になります。