結果

問題 No.448 ゆきこーだーの雨と雪 (3)
ユーザー まいん-まいん-
提出日時 2017-03-13 00:55:43
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 135 ms / 2,000 ms
コード長 3,223 bytes
コンパイル時間 618 ms
コンパイル使用メモリ 67,152 KB
実行使用メモリ 15,920 KB
最終ジャッジ日時 2024-06-30 00:37:38
合計ジャッジ時間 4,402 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,940 KB
testcase_03 AC 1 ms
6,944 KB
testcase_04 AC 1 ms
6,940 KB
testcase_05 AC 2 ms
6,944 KB
testcase_06 AC 2 ms
6,940 KB
testcase_07 AC 2 ms
6,940 KB
testcase_08 AC 2 ms
6,944 KB
testcase_09 AC 2 ms
6,940 KB
testcase_10 AC 2 ms
6,944 KB
testcase_11 AC 2 ms
6,940 KB
testcase_12 AC 2 ms
6,944 KB
testcase_13 AC 19 ms
6,944 KB
testcase_14 AC 22 ms
6,944 KB
testcase_15 AC 56 ms
8,576 KB
testcase_16 AC 90 ms
12,988 KB
testcase_17 AC 96 ms
13,332 KB
testcase_18 AC 16 ms
6,940 KB
testcase_19 AC 124 ms
15,020 KB
testcase_20 AC 43 ms
6,940 KB
testcase_21 AC 125 ms
15,000 KB
testcase_22 AC 47 ms
8,064 KB
testcase_23 AC 126 ms
15,168 KB
testcase_24 AC 30 ms
6,944 KB
testcase_25 AC 124 ms
15,076 KB
testcase_26 AC 15 ms
6,940 KB
testcase_27 AC 93 ms
12,940 KB
testcase_28 AC 84 ms
10,496 KB
testcase_29 AC 49 ms
8,192 KB
testcase_30 AC 127 ms
15,228 KB
testcase_31 AC 19 ms
6,940 KB
testcase_32 AC 20 ms
6,944 KB
testcase_33 AC 135 ms
15,804 KB
testcase_34 AC 131 ms
15,872 KB
testcase_35 AC 134 ms
15,756 KB
testcase_36 AC 126 ms
15,920 KB
testcase_37 AC 134 ms
15,860 KB
testcase_38 AC 135 ms
15,824 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

using ll = long long;

// 最大値を計算するSegment tree
template <typename T>
struct SegmentTree {
    const T DEFULT_VAL = -1;

    vector<T> dat;
    int end;

    SegmentTree(vector<T>& d) {
        int n = d.size();
        end = 1;
        while (end < n) end *= 2;

        dat.resize(2 * end - 1, DEFULT_VAL);

        for (int id = 2 * end - 2; id >= 0; id--) {
            if (2 * end - 2 - id < end) {
                int idx = id - end + 1;
                dat[id] = idx < n ? d[idx] : DEFULT_VAL;
            } else {
                dat[id] = max(dat[id * 2 + 1], dat[id * 2 + 2]);
            }
        }
    }

    void update(int idx, T a) {
        int id = idx + end - 1;
        dat[id] = a;
        while (id > 0) {
            id = (id - 1) / 2;
            dat[id] = max(dat[id * 2 + 1], dat[id * 2 + 2]);
        }
    }

    T query(int lb, int ub) {
        return query(lb, ub, 0, 0, end);
    }

    T query(int lb, int ub, int id, int node_lb, int node_ub) {
        if (node_ub <= lb || ub <= node_lb) { return DEFULT_VAL; }

        if (lb <= node_lb && node_ub <= ub) { return dat[id]; }
        else {
            int vl = query(lb, ub, id * 2 + 1, node_lb, (node_lb + node_ub) / 2),
                vr = query(lb, ub, id * 2 + 2, (node_lb + node_ub) / 2, node_ub);
            return max(vl, vr);
        }
    }
};

const ll INF = (1LL << 48);
const int MAX_N = 200010;

/*
 * next_node[i]:=i番目の仕事をyukiさんに任せた場合,
 *               次に任せることができる最短の時間
 */
int n, next_node[MAX_N];

ll k;
vector<ll> t, d, table, cum_d, max_d;

/*
 * dp[i]:=難しさub以下の仕事のみを担当し, i-1番目の仕事まで
 *        終えたときの時間の最小の総和
 */
void calc_dp(ll ub) {
    fill(table.begin(), table.end(), INF);
    table[0] = 0;

    for (int i = 0; i < n; i++) {
        if (d[i] <= ub) {
            table[i + 1] = min(table[i + 1], table[i] + d[i]);
        }
        if (max_d[i] <= ub) {
            int next = next_node[i];
            table[next] = min(table[next],
                              table[i] + cum_d[next - 1] - cum_d[i]);
        }
    }
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> k;

    t.resize(n);
    d.resize(n);
    table.resize(n + 1);
    cum_d.resize(n, 0);
    max_d.resize(n, 0);

    for (int i = 0; i < n; i++) {
        cin >> t[i] >> d[i];

        // dの累積和を計算
        cum_d[i] = d[i];
        if (i > 0) {
            cum_d[i] += cum_d[i - 1];
        }
    }

    SegmentTree<ll> segtree(d);

    for (int i = 0; i < n; i++) {
        // 次の遷移先を計算
        next_node[i] = lower_bound(t.begin() + i + 1, t.begin() + n, t[i] + k) - t.begin();
        max_d[i] = segtree.query(i + 1, next_node[i]);
    }

    ll lb = -1, ub = INF, sum = 0;
    while (ub - lb > 1) {
        ll mid = (ub + lb) / 2;
        calc_dp(mid);
        if (table[n] < INF) {
            ub = mid;
            sum = table[n];
        } else {
            lb = mid;
        }
    }
    cout << ub << endl;
    cout << sum << endl;

    return 0;
}
0