답안 #673252

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
673252 2022-12-20T03:39:49 Z Cyanmond Discharging (NOI20_discharging) C++17
11 / 100
855 ms 227252 KB
#include <bits/stdc++.h>

using i64 = long long;
constexpr i64 inf = 1ll << 60;

class SparseTable {
    int n;
    std::vector<int> log_table;
    std::vector<std::vector<i64>> data;

  public:
    SparseTable(std::vector<i64> vec) : n(vec.size()) {
        log_table.assign(n + 1, 0);
        for (int i = 1; i <= n; ++i) {
            log_table[i] = std::max(log_table[i], log_table[i - 1]);
            if (2 * i <= n) {
                log_table[2 * i] = log_table[i] + 1;
            }
        }

        data.resize(log_table[n] + 1);
        data[0] = vec;
        for (int d = 1; d <= log_table[n]; ++d) {
            const int w = 1 << d;
            data[d].resize(n - w + 1);
            for (int i = 0; i + w <= n; ++i) {
                data[d][i] = std::max(data[d - 1][i], data[d - 1][i + w / 2]);
            }
        }
    }

    i64 fold(int l, int r) const {
        const int w = r - l;
        const int d = log_table[w];
        return std::max(data[d][l], data[d][r - (1 << d)]);
    }
};

class SegmentTree {
    int n, size;
    std::vector<i64> data;

  public:
    SegmentTree(int n_) : n(n_) {
        size = 1;
        while (size < n) {
            size *= 2;
        }
        data.assign(2 * size, inf);
    }

    void set(int i, i64 v) {
        i += size;
        data[i] = v;
        while (i != 1) {
            i /= 2;
            data[i] = std::min(data[2 * i], data[2 * i + 1]);
        }
    }

    i64 fold(int l, int r) {
        i64 ret = inf;
        for (l += size, r += size; l < r; l /= 2, r /= 2) {
            if (l % 2 == 0) {
                ret = std::min(ret, data[l++]);
            }
            if (r % 2 == 0) {
                ret = std::min(ret, data[--r]);
            }
        }
        return ret;
    }
};

class LiChaoTree {
    struct Line {
        i64 a, b;
        i64 get(i64 x) const {
            return a * x + b;
        }
    }; 

    int n, seg_size;
    std::vector<Line> data;
    std::stack<std::tuple<int, int, Line, Line>> stk;

  public:
    LiChaoTree(int n_) : n(n_) {
        seg_size = 1;
        while (seg_size < n) {
            seg_size *= 2;
        }
        data.assign(2 * seg_size, {0, inf});
    }

    void update(int id, const Line &x) {
        update(id, x, 1, 0, seg_size);
    }

    void rollback(int lm) {
        while (not stk.empty()) {
            const auto [id, i, pv, nw] = stk.top();
            if (lm > id) {
                break;
            }
            stk.pop();
            data[i] = pv;
        }
    }

    i64 get(int x) {
        int xi = x;
        xi += seg_size;
        i64 res = inf;
        while (xi != 0) {
            res = std::min(res, data[xi].get(x));
            xi /= 2;
        }
        return res;
    }

  private:
    void update(int id, const Line &x, int k, int l, int r) {
        const int m = (l + r) / 2;
        bool l_over = data[k].get(l) > x.get(l), r_over = data[k].get(r - 1) > x.get(r - 1);
        if (l_over == r_over) {
            if (l_over) {
                stk.push({id, k, data[k], x});
                data[k] = x;
            }
            return;
        }
        bool m_over = data[k].get(m) > x.get(m);
        if (m_over) {
            stk.push({id, k, data[k], x});
            data[k] = x;
        }
        if (l_over) {
            update(id, x, 2 * k, l, m);
        }
        if (r_over) {
            update(id, x, 2 * k + 1, l, r);
        }
    }
};

int main() {
    int N;
    std::cin >> N;
    std::vector<i64> T(N);
    for (auto &e : T) {
        std::cin >> e;
    }
    T.push_back(0);
    std::reverse(T.begin(), T.end());
    const auto st = SparseTable(T);

    SegmentTree dp(N + 1);
    dp.set(0, 0);
    LiChaoTree tree(N + 1);
    tree.update(0, {0, 0});
    for (int i = 1; i <= N; ++i) {
        int l = -1, r = i;
        while (r - l > 1) {
            const auto mid = (l + r) / 2;
            if (st.fold(mid, i) > T[i]) {
                l = mid;
            } else {
                r = mid;
            }
        }
        tree.rollback(r);
        tree.update(i, {T[i], dp.fold(l == -1 ? 0 : l, i)});
        dp.set(i, tree.get(i));
    }

    std::cout << dp.fold(N, N + 1) << std::endl;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 1 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 300 KB Output is correct
5 Correct 1 ms 212 KB Output is correct
6 Correct 1 ms 296 KB Output is correct
7 Correct 1 ms 296 KB Output is correct
8 Correct 1 ms 212 KB Output is correct
9 Correct 1 ms 212 KB Output is correct
10 Correct 1 ms 212 KB Output is correct
11 Correct 1 ms 212 KB Output is correct
12 Correct 0 ms 304 KB Output is correct
13 Correct 1 ms 212 KB Output is correct
14 Incorrect 1 ms 212 KB Output isn't correct
15 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 2 ms 444 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 2 ms 444 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 818 ms 227132 KB Output is correct
2 Correct 803 ms 227228 KB Output is correct
3 Correct 803 ms 227124 KB Output is correct
4 Correct 842 ms 227228 KB Output is correct
5 Correct 791 ms 227152 KB Output is correct
6 Correct 807 ms 227228 KB Output is correct
7 Correct 798 ms 227236 KB Output is correct
8 Correct 822 ms 227240 KB Output is correct
9 Correct 855 ms 227136 KB Output is correct
10 Correct 827 ms 227252 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 1 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 300 KB Output is correct
5 Correct 1 ms 212 KB Output is correct
6 Correct 1 ms 296 KB Output is correct
7 Correct 1 ms 296 KB Output is correct
8 Correct 1 ms 212 KB Output is correct
9 Correct 1 ms 212 KB Output is correct
10 Correct 1 ms 212 KB Output is correct
11 Correct 1 ms 212 KB Output is correct
12 Correct 0 ms 304 KB Output is correct
13 Correct 1 ms 212 KB Output is correct
14 Incorrect 1 ms 212 KB Output isn't correct
15 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 1 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 0 ms 300 KB Output is correct
5 Correct 1 ms 212 KB Output is correct
6 Correct 1 ms 296 KB Output is correct
7 Correct 1 ms 296 KB Output is correct
8 Correct 1 ms 212 KB Output is correct
9 Correct 1 ms 212 KB Output is correct
10 Correct 1 ms 212 KB Output is correct
11 Correct 1 ms 212 KB Output is correct
12 Correct 0 ms 304 KB Output is correct
13 Correct 1 ms 212 KB Output is correct
14 Incorrect 1 ms 212 KB Output isn't correct
15 Halted 0 ms 0 KB -