Submission #995520

#TimeUsernameProblemLanguageResultExecution timeMemory
995520shiomusubi496Meetings (IOI18_meetings)C++17
41 / 100
1500 ms53832 KiB
#include "meetings.h"
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep2(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define rrep2(i, a, b) for (int i = (int)(b) - 1; i >= (int)(a); --i)
#define all(v) begin(v), end(v)
#define rall(v) rbegin(v), rend(v)

using namespace std;

using ll = long long;

template<class T, class U> bool chmin(T& a, const U& b) { return a > b ? a = b, true : false; }
template<class T, class U> bool chmax(T& a, const U& b) { return a < b ? a = b, true : false; }

template<class M>
class SparseTable {
    using T = typename M::T;
    int n, h;
    vector<vector<T>> dat;

public:
    SparseTable(vector<T> a) {
        n = a.size();
        h = __lg(n) + 1;
        dat.assign(h + 1, vector<T>(n, M::id()));
        rep (i, n) dat[0][i] = a[i];
        rep (i, h) rep (j, n - (1 << i)) {
            dat[i + 1][j] = M::op(dat[i][j], dat[i][j + (1 << i)]);
        }
    }
    T prod(int l, int r) const {
        assert(0 <= l && l <= r && r <= n);
        if (l == r) return M::id();
        int i = __lg(r - l);
        return M::op(dat[i][l], dat[i][r - (1 << i)]);
    }

    template<class F>
    int min_left(int r, F f) const {
        assert(0 <= r && r <= n);
        assert(f(M::id()));
        if (r == 0) return 0;
        int ok = r, ng = -1;
        while (ok - ng > 1) {
            int mid = (ok + ng) / 2;
            (f(prod(mid, r)) ? ok : ng) = mid;
        }
        return ok;
    }
    template<class F>
    int max_right(int l, F f) const {
        assert(0 <= l && l <= n);
        assert(f(M::id()));
        if (l == n) return n;
        int ok = l, ng = n + 1;
        while (ng - ok > 1) {
            int mid = (ok + ng) / 2;
            (f(prod(l, mid)) ? ok : ng) = mid;
        }
        return ok;
    }
};

constexpr int inf = 1.01e9;
constexpr ll infl = 1e18;

struct Min {
    using T = int;
    static T op(T a, T b) { return min(a, b); }
    static T id() { return inf; }
};

class StarrySkyTree {
    int n;
    vector<ll> dat;

    void add_(int k, int a, int b, int l, int r, ll x) {
        if (b <= l || r <= a) return;
        if (l <= a && b <= r) {
            dat[k] += x;
            return;
        }
        int m = (a + b) / 2;
        add_(2 * k, a, m, l, r, x);
        add_(2 * k + 1, m, b, l, r, x);
        ll mn = max(dat[2 * k], dat[2 * k + 1]);
        dat[k] += mn;
        dat[2 * k] -= mn;
        dat[2 * k + 1] -= mn;
    }
    ll prod(int k, int a, int b, int l, int r, ll x) {
        if (b <= l || r <= a) return -infl;
        if (l <= a && b <= r) return dat[k] + x;
        int m = (a + b) / 2;
        ll vl = prod(2 * k, a, m, l, r, x + dat[k]);
        ll vr = prod(2 * k + 1, m, b, l, r, x + dat[k]);
        return max(vl, vr);
    }

public:
    StarrySkyTree(int n_) {
        n = 1;
        while (n < n_) n <<= 1;
        dat.assign(2 * n, 0);
    }
    void add(int l, int r, ll x) { add_(1, 0, n, l, r, x); }
    ll prod(int l, int r) { return prod(1, 0, n, l, r, 0); }
};

std::vector<long long> minimum_costs(std::vector<int> H, std::vector<int> L, std::vector<int> R) {
    int N = H.size();
    rep (i, N) H[i] = 20 - H[i];
    int Q = L.size();
    rep (i, Q) ++R[i];
    vector<ll> ans(Q);
    SparseTable<Min> st(H);
    StarrySkyTree seg(N);

    vector<vector<ll>> memoL(N, vector<ll>(21, 0));
    vector<vector<ll>> memoR(N, vector<ll>(21, 0));

    rep (i, N) {
        int cur = i;
        ll sm = 0;
        rrep (j, 20) {
            if (H[cur] < j) continue;
            int l = st.min_left(cur, [&](int x) { return x >= j; });
            memoL[i][j] = cur - l + 1;
            sm += j * (cur - l + 1);
            cur = l - 1;
            if (cur < 0) break;
        }
        --memoL[i][H[i]];
        cur = i;
        rrep (j, 20) {
            if (H[cur] < j) continue;
            int r = st.max_right(cur + 1, [&](int x) { return x >= j; });
            memoR[i][j] = r - cur;
            sm += j * (r - cur);
            cur = r;
            if (cur >= N) break;
        }
        --memoR[i][H[i]];
        sm -= H[i];
        seg.add(i, i + 1, sm);
    }

    rep (i, Q) {
        {
            int cur = L[i];
            rrep (j, 20) {
                if (H[cur] < j) continue;
                ll sm = 0;
                rep (k, 20) sm += min(j, k) * memoL[L[i]][k];
                int r = st.max_right(cur, [&](int x) { return x >= j; });
                seg.add(cur, r, -sm);
                cur = r;
                if (cur >= R[i]) break;
            }
            cur = R[i];
            rrep (j, 20) {
                if (H[cur] < j) continue;
                ll sm = 0;
                rep (k, 20) sm += min(j, k) * memoR[R[i] - 1][k];
                int l = st.min_left(cur, [&](int x) { return x >= j; });
                seg.add(l, cur, -sm);
                cur = l;
                if (cur <= L[i]) break;
            }
        }
        ans[i] = seg.prod(L[i], R[i]);
        {
            int cur = L[i];
            rrep (j, 20) {
                if (H[cur] < j) continue;
                ll sm = 0;
                rep (k, 20) sm += min(j, k) * memoL[L[i]][k];
                int r = st.max_right(cur, [&](int x) { return x >= j; });
                seg.add(cur, r, sm);
                cur = r;
                if (cur >= R[i]) break;
            }
            cur = R[i];
            rrep (j, 20) {
                if (H[cur] < j) continue;
                ll sm = 0;
                rep (k, 20) sm += min(j, k) * memoR[R[i] - 1][k];
                int l = st.min_left(cur, [&](int x) { return x >= j; });
                seg.add(l, cur, sm);
                cur = l;
                if (cur <= L[i]) break;
            }
        }
    }

    rep (i, Q) ans[i] = 20 * (R[i] - L[i]) - ans[i];
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...