結果

問題 No.448 ゆきこーだーの雨と雪 (3)
ユーザー まいん-
提出日時 2017-03-13 00:39:26
言語 C++11(廃止可能性あり)
(gcc 13.3.0)
結果
AC  
実行時間 1,792 ms / 2,000 ms
コード長 2,856 bytes
コンパイル時間 1,082 ms
コンパイル使用メモリ 71,768 KB
実行使用メモリ 15,940 KB
最終ジャッジ日時 2025-04-24 22:14:10
合計ジャッジ時間 33,137 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 35
権限があれば一括ダウンロードができます

ソースコード

diff #

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

using ll = long long;

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 << 60);
const int MAX_N = 200010;

int n, next_node[MAX_N];

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

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 >> 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];

        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]);

        cerr << "(" << next_node[i] << ", " << max_d[i] << ")" << endl;
    }

    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