Submission #70453829


Source Code Expand

/** @type {(a: unknown, b: unknown) => number} Array#sort()でcompareFnを指定しなかったときのデフォルトの挙動と同じ挙動を示す比較関数 */
const DEFAULT_COMPARE_FN = (a, b) => {
    const [A, B] = [String(a), String(b)];
    return (A < B) ? -1 : (A > B) ? 1 : 0
};
/** @template {any} T */
/** @type {(array: T[], target: T, compareFn?: (a: T, b: T) => number) => boolean} 配列`array`に`target`と等しい値が存在するかどうかを、二分探索を用いて判定する。 */
const binary_search = (array, target, compareFn = DEFAULT_COMPARE_FN) => {
    let low = 0;
    let high = array.length - 1;

    while (low <= high) {
        const mid = Math.floor((low + high) / 2);
        const cmp = compareFn(array[mid], target);

        if (cmp === 0) return true;
        if (cmp < 0) low = mid + 1;
        else high = mid - 1;
    }

    return false;
};
/** @template {any} T */
/** @type {(array: T[], target: T, compareFn?: (a: T, b: T) => number) => number} 配列`array`の中で、`target`以上と判定される最初の要素のインデックスを返す。(`array`内に`target`以上の要素が存在しない場合は`array.length`を返す。) */
const lower_bound = (array, target, compareFn = DEFAULT_COMPARE_FN) => {
    let low = 0;
    let high = array.length;

    while (low < high) {
        const mid = Math.floor((low + high) / 2);
        const cmp = compareFn(array[mid], target);

        if (cmp < 0) low = mid + 1;
        else high = mid;
    }

    return low;
};
/** @template {any} T */
/** @type {(array: T[], target: T, compareFn?: (a: T, b: T) => number) => number} 配列`array`の中で、`target`より大きいと判定される最初の要素のインデックスを返す。(`array`内に`target`より大きい要素が存在しない場合は`array.length`) */
const upper_bound = (array, target, compareFn = DEFAULT_COMPARE_FN) => {
    let low = 0;
    let high = array.length;

    while (low < high) {
        const mid = Math.floor((low + high) / 2);
        const cmp = compareFn(array[mid], target);

        if (cmp <= 0) low = mid + 1;
        else high = mid;
    }

    return low;
};

// ==== ここからほんへ ====
const inputText = await Deno.readTextFile("/dev/stdin");
const input = inputText.trim().split("\n").map(row => row.split(" "));
(() => {
    // 処理
    const [N, M, C] = input[0].map(n => +n);
    const A = input[1].map(n => +n);
    
    // Aを3周分に伸ばしてソートしてランレングス圧縮します
    for (let i = 0; i < N; i++) {
        A.push(A[i] + M);
        A.push(A[i] - M);
    }
    A.sort((a, b) => a - b);
    const A_compressed = [];
    (() => {
        let latest;
        A.forEach((Ai) => {
            if (latest?.pos !== Ai) {
                if (latest != null) {
                    A_compressed.push(latest);
                }
                latest = { "pos": Ai, "humans": 1 };
            } else {
                latest.humans++;
            }
        });
        if (latest != null) {
            A_compressed.push(latest);
        }  
    })();
    
    // A_compressedに「そこまでに何人いるか(そこ含む)の情報(total)を追加します」
    (() => {
        let all_count = 0;
        A_compressed.forEach(Ai => {
            all_count += Ai.humans;
            Ai.total = all_count;
        });
    })();
    // console.log(A_compressed); // 確認用 (posに場所、humansに人数、totalに合計人数)
    
    // このあとにぶたんするのでtotalの比較関数作っておきます
    const TOTAL_COMPARE_FN = (a, b) => a.total - b.total;
    
    // posが1以上である人を先頭として1周するまで、
    // 「その人達が第一村人のとき高橋君が何人に出会うか」と
    // 「その人達が第一村人なiの数」を求めて掛け算すると良いと思います
    // posが1以上である最初の集団のA_compressedにおけるindex
    const headTargetIndex = A_compressed[A_compressed.length / 3].pos === 0
        ? A_compressed.length / 3 + 1
        : A_compressed.length / 3;
    // A_compressedのどこまで見ればいいか(index)
    const tailTargetIndex = headTargetIndex + (A_compressed.length / 3) - 1;
    // A_compressedの当該範囲をループしながら回答を足していきます
    let sum = 0;
    // console.log(headTargetIndex, tailTargetIndex); // 確認用
    for (let i = headTargetIndex; i <= tailTargetIndex; i++) {
        // 今回先頭とする集団
        const targetGroup = A_compressed[i];
        // 1個前の集団
        const latestGroup = A_compressed[i - 1];
        // totalが何**以上**になったら止まるか(CにlatestGroup.totalを足せばOK)
        const stopOnTotalIsOver = C + latestGroup.total;
        // totalがstopOnTotalIsOver以上な最初のA_compressedの要素のindex
        const stopperGroupsIndex = lower_bound(
            A_compressed,
            { "total": stopOnTotalIsOver },
            TOTAL_COMPARE_FN
        );
        // 高橋君を止めたグループに対応するA_compressedの要素
        const stopperGroup = A_compressed[stopperGroupsIndex];
        // stopperGroupまで(stopperGroup含む)のtotal
        const total_onStopperGroup = stopperGroup.total;
        // <!> targetGroupが第一村人のときの出会う人数
        const X_ifFirstIsTargetGroup = total_onStopperGroup - latestGroup.total;
        // 第一村人がtargetGroupであるiの下限 (= latestGroupのpos)
        const i_min = latestGroup.pos;
        // 第一村人がtargetGroupであるiの上限 (= targetGroupのpos - 1)
        const i_max = targetGroup.pos - 1;
        // 第一村人がtargetGroupであるiの数 (i_max - i_min + 1)
        const i_count = i_max - i_min + 1;
        // 足す
        sum += X_ifFirstIsTargetGroup * i_count;
        // console.log(sum, X_ifFirstIsTargetGroup, i_count); // 確認用
    }
    console.log(sum);
})();

Submission Info

Submission Time
Task D - On AtCoder Conference
User AXT_AyaKoto
Language JavaScript (Deno 1.35.1)
Score 0
Code Size 6157 Byte
Status WA
Exec Time 1545 ms
Memory 298712 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 0 / 425
Status
AC × 2
AC × 17
WA × 15
Set Name Test Cases
Sample example_00.txt, example_01.txt
All example_00.txt, example_01.txt, hand_00.txt, hand_01.txt, hand_02.txt, hand_03.txt, hand_04.txt, hand_05.txt, random_00.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt, random_20.txt, random_21.txt, random_22.txt, random_23.txt
Case Name Status Exec Time Memory
example_00.txt AC 68 ms 43660 KiB
example_01.txt AC 66 ms 43376 KiB
hand_00.txt AC 465 ms 180256 KiB
hand_01.txt AC 381 ms 180356 KiB
hand_02.txt AC 1545 ms 298712 KiB
hand_03.txt AC 171 ms 101808 KiB
hand_04.txt AC 68 ms 43656 KiB
hand_05.txt AC 65 ms 43320 KiB
random_00.txt AC 427 ms 117624 KiB
random_01.txt AC 428 ms 119220 KiB
random_02.txt AC 447 ms 126636 KiB
random_03.txt AC 607 ms 143184 KiB
random_04.txt AC 608 ms 151512 KiB
random_05.txt AC 604 ms 144728 KiB
random_06.txt AC 820 ms 225536 KiB
random_07.txt AC 815 ms 224804 KiB
random_08.txt AC 802 ms 221408 KiB
random_09.txt WA 535 ms 184992 KiB
random_10.txt WA 459 ms 181660 KiB
random_11.txt WA 489 ms 186176 KiB
random_12.txt WA 534 ms 186388 KiB
random_13.txt WA 737 ms 187436 KiB
random_14.txt WA 721 ms 187284 KiB
random_15.txt WA 549 ms 187348 KiB
random_16.txt WA 866 ms 187232 KiB
random_17.txt WA 881 ms 187240 KiB
random_18.txt WA 599 ms 193100 KiB
random_19.txt WA 1050 ms 188920 KiB
random_20.txt WA 1037 ms 189848 KiB
random_21.txt WA 1198 ms 216616 KiB
random_22.txt WA 1307 ms 212176 KiB
random_23.txt WA 1472 ms 286272 KiB