結果

問題 No.568 じゃんじゃん 落とす 委員会
ユーザー nebukuro09nebukuro09
提出日時 2017-09-09 00:16:26
言語 D
(dmd 2.106.1)
結果
TLE  
実行時間 -
コード長 3,369 bytes
コンパイル時間 775 ms
コンパイル使用メモリ 112,740 KB
実行使用メモリ 12,656 KB
最終ジャッジ日時 2023-09-03 16:11:14
合計ジャッジ時間 26,190 ms
ジャッジサーバーID
(参考情報)
judge12 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 141 ms
9,900 KB
testcase_01 AC 141 ms
9,568 KB
testcase_02 TLE -
testcase_03 TLE -
testcase_04 TLE -
testcase_05 AC 5 ms
6,948 KB
testcase_06 TLE -
testcase_07 TLE -
testcase_08 TLE -
testcase_09 AC 5 ms
6,928 KB
testcase_10 AC 5 ms
6,944 KB
testcase_11 TLE -
testcase_12 AC 141 ms
9,848 KB
testcase_13 TLE -
testcase_14 TLE -
testcase_15 TLE -
testcase_16 AC 878 ms
10,368 KB
testcase_17 AC 133 ms
8,992 KB
testcase_18 TLE -
testcase_19 TLE -
testcase_20 AC 330 ms
9,280 KB
testcase_21 TLE -
testcase_22 AC 140 ms
11,240 KB
testcase_23 TLE -
testcase_24 AC 5 ms
7,008 KB
testcase_25 AC 5 ms
8,260 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop;

alias Tuple!(int, "a", int, "b") Score;
const int MAX = 10^^5 + 10;

void main() {
    auto t = readln.split.map!(to!int);
    auto N = t[0];
    auto M = t[1];
    Score[] s0;
    Score[] s1;
    Score[] s2;
    int cnt2 = 0;
    int cnt3 = 0;
    foreach (i; 0..N) {
        t = readln.split.map!(to!int);
        if (t[0] == 0)
            s0 ~= Score(t[1], t[2]);
        else if (t[0] == 1)
            s1 ~= Score(t[1], t[2]);
        else if (t[0] == 2)
            s2 ~= Score(t[1], t[2]), cnt2 += 1;
        else
            cnt2 += 1, cnt3 += 1;
    }


    int ans = 1 << 29;
    s0.sort!"a[0] < b[0]";
    s1.sort!"a[0] < b[0]";
    s2.sort!"a[0] < b[0]";
    auto st0 = new SegmentTree(MAX);
    auto st1a = new SegmentTree(MAX);
    auto st1b = new SegmentTree(MAX);
    auto st2 = new SegmentTree(MAX);
    int p0 = s0.length.to!int - 1;
    int p1 = s1.length.to!int - 1;
    int p2 = s2.length.to!int - 1;

    foreach (s; s1)
        st1b.add(s.b, 1);
    foreach (s; s2)
        st2.add(s.b, 1);


    for (int a = MAX - 1; a >= 0; --a) {

        for (; p0 >= 0 && s0[p0].a == a; p0--)
            st0.add(s0[p0].b, 1);
        for (; p1 >= 0 && s1[p1].a == a; p1--) {
            st1a.add(s1[p1].b, 1);
            st1b.add(s1[p1].b, -1);
            cnt2 += 1;
        }
        for (; p2 >= 0 && s2[p2].a == a; p2--) {
            st2.add(s2[p2].b, -1);
            cnt3 += 1;
        }

        int target = M - cnt2;
        if (target <= 0) {
            ans = min(ans, cnt3);
            continue;
        }

        int hi = MAX-1;
        int lo = -1;
        while (hi - lo > 1) {
            int mid = (hi + lo) / 2;
            int tmp2 = 0;
            tmp2 += st0.sum(mid, MAX);
            tmp2 += st1b.sum(mid, MAX);
            if (tmp2 < target)
                hi = mid;
            else
                lo = mid;
        }

        if (lo == -1)
            continue;

        int tmp3 = 0;
        tmp3 += st1a.sum(lo, MAX);
        tmp3 += st2.sum(lo, MAX);
        ans = min(ans, cnt3 + tmp3);
        //if (a <= 100)
        //    writeln([a, lo, cnt2, cnt3, tmp3, ans, st0.sum(lo,MAX)+st1b.sum(lo,MAX), p0, p1, p2]);
    }

    ans.writeln;
}


class SegmentTree {
    int[] table;
    int size;

    this(int n) {
        assert(bsr(n) < 29);
        size = 1 << (bsr(n) + 2);
        table = new int[](size);
    }

    void add(int pos, int num) {
        return add(pos, num, 0, 0, size/2-1);
    }

    void add(int pos, int num, int i, int left, int right) {
        table[i] += num;
        if (left == right)
            return;
        auto mid = (left + right) / 2;
        if (pos <= mid)
            add(pos, num, i*2+1, left, mid);
        else
            add(pos, num, i*2+2, mid+1, right);
    }

    int sum(int pl, int pr) {
        return sum(pl, pr, 0, 0, size/2-1);
    }

    int sum(int pl, int pr, int i, int left, int right) {
        if (pl > right || pr < left)
            return 0;
        else if (pl <= left && right <= pr)
            return table[i];
        else
            return
                sum(pl, pr, i*2+1, left, (left+right)/2) +
                sum(pl, pr, i*2+2, (left+right)/2+1, right);
    }
}
0