結果

問題 No.576 E869120 and Rings
ユーザー 明智重蔵明智重蔵
提出日時 2022-12-31 10:17:07
言語 C#(csc)
(csc 3.9.0)
結果
MLE  
実行時間 -
コード長 6,055 bytes
コンパイル時間 837 ms
コンパイル使用メモリ 111,616 KB
実行使用メモリ 222,500 KB
最終ジャッジ日時 2024-05-04 18:57:54
合計ジャッジ時間 6,807 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 MLE -
testcase_01 -- -
testcase_02 -- -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
権限があれば一括ダウンロードができます
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc)
Copyright (C) Microsoft Corporation. All rights reserved.

ソースコード

diff #

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("8 4");
            WillReturn.Add("11101110");
            //0.857142857142857
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("8 4");
            WillReturn.Add("11011001");
            //0.833333333333333
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("10 4");
            WillReturn.Add("1001001001");
            //0.6
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static int mN;
    static int mK;

    static List<double> mAList = new List<double>();

    static void Main()
    {
        List<string> InputList = GetInputList();
        int[] wkArr = InputList[0].Split(' ').Select(pX => int.Parse(pX)).ToArray();
        mN = wkArr[0];
        mK = wkArr[1];

        string AStr = InputList[1];
        foreach (char EachA in AStr) {
            if (EachA == '0') mAList.Add(0);
            if (EachA == '1') mAList.Add(1);
        }

        // 全て1の場合
        if (mAList.TrueForAll(pX => pX == 1D)) {
            Console.WriteLine(1);
            return;
        }

        // 答えで二分探索
        double L = 0;
        double R = 1;

        while (L + 0.0000000001 < R) {
            double Mid = (L + R) / 2;

            bool Result = CanAchieve(Mid);
            //Console.WriteLine("L={0},Mid={1},R={2},Result={3}", L, Mid, R, Result);
            if (Result) {
                L = Mid;
            }
            else {
                R = Mid;
            }
        }
        Console.WriteLine(R);
    }

    // NeedAVGを達成できるかを判定
    static bool CanAchieve(double pNeedAVG)
    {
        // 取得区間はK以上N以下なので、2倍の長さにしておく
        var CompareList = new List<double>();
        for (int I = 1; I <= 2; I++) {
            foreach (double EachA in mAList) {
                CompareList.Add(EachA - pNeedAVG);
            }
        }
        int UB = CompareList.Count - 1;

        // 累積和を設定する
        for (int I = 1; I <= UB; I++) {
            CompareList[I] += CompareList[I - 1];
        }

        var InsSparseTable = new SparseTable<double>(CompareList, true);

        // 終端を全探索
        for (int I = 0; I <= UB; I++) {
            // 長さKの区間を取れなければcontinue
            if (I - mK + 1 < 0) continue;

            // 始点候補のSta
            int RangeSta = I - mN + 1;
            RangeSta = Math.Max(0, RangeSta);
            RangeSta--;
            RangeSta = Math.Max(0, RangeSta);

            // 始点候補のEnd
            int RangeEnd = I - mK + 1;
            RangeEnd--;
            RangeEnd = Math.Max(0, RangeEnd);

            double RangeMin = InsSparseTable.Query(RangeSta, RangeEnd);
            if (CompareList[I] - RangeMin >= 0) return true;
        }
        return false;
    }
}

#region SparseTable
// スパーステーブル
internal class SparseTable<Type>
{
    private Type[] mInitArr;
    private int UB_0;
    private int UB_1;

    // 最小値か最大値[開始Ind,2の指数]なArr
    private Type[,] mMinOrMaxArr;

    // Log2の値[2べきな値] なDict
    static Dictionary<int, int> mLogDict = new Dictionary<int, int>();

    // 最小値を取得するか?
    private bool mIsMin = false;

    // コンストラクタ
    internal SparseTable(IEnumerable<Type> pInitEnum, bool pIsMin)
    {
        mIsMin = pIsMin;

        mInitArr = pInitEnum.ToArray();
        UB_0 = mInitArr.GetUpperBound(0);

        int Sisuu = 0;
        int Beki2 = 1;
        while (true) {
            mLogDict[Beki2] = Sisuu;
            if (Beki2 > mInitArr.Length) {
                break;
            }
            Beki2 *= 2;
            Sisuu++;
        }
        UB_1 = Sisuu;

        mMinOrMaxArr = new Type[UB_0 + 1, UB_1 + 1];

        // 長さ1の分を初期化
        for (int I = 0; I <= UB_0; I++) {
            mMinOrMaxArr[I, 0] = mInitArr[I];
        }

        for (int LoopLength = 2; LoopLength < int.MaxValue; LoopLength *= 2) {
            bool WillBreak = true;
            int HalfRange = LoopLength / 2;
            for (int I = 0; I <= UB_0; I++) {
                int StaInd1 = I;
                int EndInd1 = I + HalfRange - 1;
                int StaInd2 = EndInd1 + 1;
                int EndInd2 = StaInd2 + HalfRange - 1;

                if (EndInd2 > UB_0) break;

                var KouhoList = new List<Type>();
                KouhoList.Add(mMinOrMaxArr[I, mLogDict[HalfRange]]);
                KouhoList.Add(mMinOrMaxArr[StaInd2, mLogDict[HalfRange]]);

                if (mIsMin) {
                    mMinOrMaxArr[I, mLogDict[LoopLength]] = KouhoList.Min();
                }
                else {
                    mMinOrMaxArr[I, mLogDict[LoopLength]] = KouhoList.Max();
                }

                WillBreak = false;
            }
            if (WillBreak) break;
        }
    }

    // 閉区間 [L,R]の最小値または最大値を求める
    internal Type Query(int pL, int pR)
    {
        // 区間を内包する2べきを返す
        int Beki2 = 1;
        int Sisuu = 0;
        while (true) {
            int LeftRangeMax = pL + Beki2 - 1;
            int RightRangeMin = pR - Beki2 + 1;

            if (LeftRangeMax + 1 >= RightRangeMin) {
                break;
            }
            Beki2 *= 2;
            Sisuu++;
        }

        var KouhoList = new List<Type>();
        KouhoList.Add(mMinOrMaxArr[pL, Sisuu]);
        KouhoList.Add(mMinOrMaxArr[pR - Beki2 + 1, Sisuu]);

        if (mIsMin) {
            return KouhoList.Min();
        }
        return KouhoList.Max();
    }
}
#endregion
0