AtCoderのABC    次のABCの問題へ    前のABCの問題へ

ABC422-C AtCoder AAC Contest


問題へのリンク


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("5");
            WillReturn.Add("3 1 2");
            WillReturn.Add("100 0 0");
            WillReturn.Add("1000000 1000000 1000000");
            WillReturn.Add("31 41 59");
            WillReturn.Add("1000000000 10000 1");
            //2
            //0
            //1000000
            //31
            //1
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static long[] GetSplitArr(string pStr)
    {
        return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
    }

    static void Main()
    {
        List<string> InputList = GetInputList();

        long[] wkArr = { };
        Action<string> SplitAct = (pStr) => wkArr = GetSplitArr(pStr);

        foreach (string EachStr in InputList.Skip(1)) {
            SplitAct(EachStr);
            long A = wkArr[0];
            long B = wkArr[1];
            long C = wkArr[2];
            long Result = Solve(A, B, C);
            Console.WriteLine(Result);
        }
    }

    static long Solve(long pA, long pB, long pC)
    {
        long Answer = 0;

        // ABCを作れるだけ作る
        var ValList = new List<long>();
        ValList.Add(pA);
        ValList.Add(pB);
        ValList.Add(pC);
        long ABCCnr = ValList.Min();
        Answer += ABCCnr;

        pA -= ABCCnr;
        pB -= ABCCnr;
        pC -= ABCCnr;

        if (pA == 0) return Answer;
        if (pC == 0) return Answer;

        // AACかACCを何個作れるかを二分探索
        long L = 0;
        long R = pA + pC;

        while (L + 1 < R) {
            long Mid = (L + R) / 2;

            if (CanAchieve(Mid, pA, pC)) {
                L = Mid;
            }
            else {
                R = Mid;
            }
        }
        Answer += L;

        return Answer;
    }

    // AACかACCをX個作れるかを返す
    static bool CanAchieve(long pX, long pA, long pC)
    {
        pA -= pX;
        pC -= pX;

        if (pA < 0) return false;
        if (pC < 0) return false;
        return pA + pC >= pX;
    }
}


解説

まず、ABCを作れるだけ作り、
その後、ARC050-B 花束の要領で二分探索してます。

コンテストをK個作れるかの判定は
先に先頭のAと末尾のCの分を引き、
残りのA+CがK以上かで判定できます。