AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC196-E Filters
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 2");
WillReturn.Add("10 1");
WillReturn.Add("10 3");
WillReturn.Add("5");
WillReturn.Add("-15 -10 -5 0 5");
//0
//0
//5
//10
//10
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct ATInfoDef
{
internal long A;
internal long T;
}
static List<ATInfoDef> mATInfoList = new List<ATInfoDef>();
static long[] mXArr;
static void Main()
{
List<string> InputList = GetInputList();
long N = int.Parse(InputList[0]);
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
foreach (string EachStr in InputList.Skip(1).Take((int)N)) {
SplitAct(EachStr);
ATInfoDef WillAdd;
WillAdd.A = wkArr[0];
WillAdd.T = wkArr[1];
mATInfoList.Add(WillAdd);
}
mXArr = InputList.Last().Split(' ').Select(pX => long.Parse(pX)).ToArray();
bool HasT2 = mATInfoList.Exists(pX => pX.T == 2);
bool HasT3 = mATInfoList.Exists(pX => pX.T == 3);
long X2 = long.MinValue;
long Y2 = long.MinValue;
if (HasT2) {
X2 = DeriveMinY_MaxX();
Y2 = DeriveResult(X2);
}
long X3 = long.MaxValue;
long Y3 = long.MaxValue;
if (HasT3) {
X3 = DeriveMaxY_MinX();
Y3 = DeriveResult(X3);
}
long ASum = mATInfoList.Sum(pX => pX.A);
var sb = new System.Text.StringBuilder();
foreach (long EachX in mXArr) {
if (EachX <= X2) {
sb.AppendLine(Y2.ToString());
continue;
}
if (X3 <= EachX) {
sb.AppendLine(Y3.ToString());
continue;
}
if (HasT2 == false && HasT3 == false) {
sb.AppendLine((EachX + ASum).ToString());
continue;
}
if (HasT2) {
long Diff = X2 - EachX;
sb.AppendLine((Y2 - Diff).ToString());
continue;
}
if (HasT3) {
long Diff = EachX - X3;
sb.AppendLine((Y3 + Diff).ToString());
continue;
}
}
Console.Write(sb.ToString());
}
// 関数を順番に適用した結果を返す
static long DeriveResult(long pX)
{
long WillReturn = pX;
foreach (ATInfoDef EachATInfo in mATInfoList) {
long T = EachATInfo.T;
long A = EachATInfo.A;
if (T == 1) {
WillReturn += A;
}
if (T == 2) {
WillReturn = Math.Max(WillReturn, A);
}
if (T == 3) {
WillReturn = Math.Min(WillReturn, A);
}
}
return WillReturn;
}
// Yが最小値になるXの最大値を求める
static long DeriveMinY_MaxX()
{
long AbsASum = mATInfoList.Sum(pX => Math.Abs(pX.A));
long MinY = DeriveResult(-AbsASum * 2);
long L = -AbsASum * 2;
long R = AbsASum * 2;
while (L + 1 < R) {
long Mid = (L + R) / 2;
if (DeriveResult(Mid) == MinY) {
L = Mid;
}
else {
R = Mid;
}
}
return L;
}
// Yが最大値になるXの最小値を求める
static long DeriveMaxY_MinX()
{
long AbsASum = mATInfoList.Sum(pX => Math.Abs(pX.A));
long MaxY = DeriveResult(AbsASum * 2);
long L = -AbsASum * 2;
long R = AbsASum * 2;
while (L + 1 < R) {
long Mid = (L + R) / 2;
if (DeriveResult(Mid) == MaxY) {
R = Mid;
}
else {
L = Mid;
}
}
return R;
}
}
解説
T=2の関数と、T=3の関数があるかで場合分けしつつ
合成関数の結果が
最小値を取る区間と最大値を取る区間
を二分法で求めてます。