Submission #1336343

#TimeUsernameProblemLanguageResultExecution timeMemory
1336343MisterReaperBodyguard (JOI21_bodyguard)C++20
100 / 100
2742 ms682020 KiB
#include <bits/stdc++.h>

using i64 = long long;

#ifdef DEBUG
    #include "debug.h"
#else
    #define debug(...) void(23)
#endif

template<typename T>
bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

int Id(std::vector<i64>& v, i64 x) {
    auto it = std::lower_bound(v.begin(), v.end(), x);
    return int(it - v.begin());
}

constexpr i64 inf = i64(1E18);

struct line {
    i64 a;
    i64 b;
    line(i64 a_, i64 b_) : a(a_), b(b_) {}
    i64 operator()(i64 x) {
        return a * x + b;
    }
};
bool intersect(line a, line b, line c) {
    return __int128_t(1) * (b.b - a.b) * (b.a - c.a) < __int128_t(1) * (a.a - b.a) * (c.b - b.b);
}
bool intersect(line a, line b, i64 x) {
    return (b.b - a.b) >= __int128_t(1) * x * (a.a - b.a);
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N, Q;
    std::cin >> N >> Q;

    std::vector<std::array<i64, 4>> gs[2];
    for (int i = 0; i < N; ++i) {
        i64 T, A, B, C;
        std::cin >> T >> A >> B >> C;
        C /= 2;
        debug(T, A, B, C);
        if (A < B) {
            gs[1].push_back({T + A, T + 2 * B - A, T - A, C});
        } else {
            gs[0].push_back({T - A, T + A - 2 * B, T + A, C});
        }
    }

    std::vector<std::array<i64, 2>> qrys(Q);
    for (int i = 0; i < Q; ++i) {
        i64 T, X;
        std::cin >> T >> X;
        debug(T, X);
        qrys[i] = {T + X, T - X};
    }

    std::vector<i64> points_x;
    std::vector<i64> points_y;
    for (auto[y1, y2, x, c] : gs[0]) {
        points_x.emplace_back(x);
        points_y.emplace_back(y1);
        points_y.emplace_back(y2);
    }
    for (auto[x1, x2, y, c] : gs[1]) {
        points_x.emplace_back(x1);
        points_x.emplace_back(x2);
        points_y.emplace_back(y);
    }

    points_x.emplace_back(-inf);
    points_x.emplace_back(inf);
    std::sort(points_x.begin(), points_x.end());
    points_x.erase(std::unique(points_x.begin(), points_x.end()), points_x.end());
    int npx = int(points_x.size());

    points_y.emplace_back(-inf);
    points_y.emplace_back(inf);
    std::sort(points_y.begin(), points_y.end());
    points_y.erase(std::unique(points_y.begin(), points_y.end()), points_y.end());
    int npy = int(points_y.size());

    for (auto&[y1, y2, x, c] : gs[0]) {
        debug(y1, y2, x, c);
        y1 = Id(points_y, y1);
        y2 = Id(points_y, y2);
        x = Id(points_x, x);
    }
    for (auto&[x1, x2, y, c] : gs[1]) {
        debug(x1, x2, y, c);
        x1 = Id(points_x, x1);
        x2 = Id(points_x, x2);
        y = Id(points_y, y);
    }

    debug(points_x);
    debug(points_y);

    std::vector<std::vector<i64>> up(npx + 1, std::vector<i64>(npy + 1));
    std::vector<std::vector<i64>> rg(npx + 1, std::vector<i64>(npy + 1));

    for (auto[y1, y2, x, c] : gs[0]) {
        for (int i = y1; i < y2; ++i) {
            chmax(rg[x][i], c);
        }
    }
    for (auto[x1, x2, y, c] : gs[1]) {
        for (int i = x1; i < x2; ++i) {
            chmax(up[i][y], c);
        }
    }

    std::vector<std::vector<i64>> f(npx + 1, std::vector<i64>(npy + 1));
    for (int i = npx - 1; i >= 0; --i) {
        for (int j = npy - 1; j >= 0; --j) {
            if (i != npx - 1) {
                chmax(f[i][j], f[i + 1][j] + up[i][j] * (points_x[i + 1] - points_x[i]));
            }
            if (j != npy - 1) {
                chmax(f[i][j], f[i][j + 1] + rg[i][j] * (points_y[j + 1] - points_y[j]));
            }
        }
        debug(points_x[i], f[i]);
    }

    // debug(rg);
    // debug(up);

    std::vector<i64> ans(Q);
    std::vector<std::vector<std::array<i64, 2>>> ask_x(npx);
    std::vector<std::vector<std::array<i64, 2>>> ask_y(npy);

    for (int qq = 0; qq < Q; ++qq) {
        auto[x, y] = qrys[qq];
        // i64 ans = 0;
        int sx = Id(points_x, x);
        int sy = Id(points_y, y);
        debug(sx, sy);
        ask_y[sy].push_back({sx, qq});
        ask_x[sx].push_back({sy, qq});
        for (int i = sx; i < npx; ++i) {
            debug(f[i][sy] + rg[i][sy - 1] * (points_y[sy] - y), f[i][sy], rg[i][sy - 1]);
            // chmax(ans, f[i][sy] + rg[i][sy - 1] * (points_y[sy] - y));
        }
        for (int j = sy; j < npy; ++j) {
            debug(f[sx][j] + up[sx - 1][j] * (points_x[sx] - x), f[sx][j], up[sx - 1][j]);
            // chmax(ans, f[sx][j] + up[sx - 1][j] * (points_x[sx] - x));
        }
        // std::cout << ans / 2 << '\n';
        debug();
    }

    for (int i = 1; i < npx; ++i) {
        std::sort(ask_x[i].begin(), ask_x[i].end(), std::greater());
        int j = npy;
        std::deque<line> deq;
        for (auto[sy, qq] : ask_x[i]) {
            auto[x, y] = qrys[qq];
            while (j > sy) {
                j--;
                line l = {up[i - 1][j], f[i][j]};
                while (!deq.empty() && deq.back().a <= l.a) {
                    deq.pop_back();
                }
                while (deq.size() >= 2 && intersect(deq.end()[-2], deq.back(), l)) {
                    deq.pop_back();
                }
                deq.emplace_back(l);
            }
            int lo = 0, hi = int(deq.size()) - 1;
            while (lo + 1 < hi) {
                int mid = (lo + hi) >> 1;
                if (intersect(deq[mid], deq[mid + 1], points_x[i] - x)) {
                    lo = mid;
                } else {
                    hi = mid;
                }
            }
            for (int k = lo; k <= hi; ++k) {
                chmax(ans[qq], deq[k](points_x[i] - x));
            }
        }
    }

    for (int j = 1; j < npy; ++j) {
        std::sort(ask_y[j].begin(), ask_y[j].end(), std::greater());
        int i = npx;
        std::deque<line> deq;
        for (auto[sx, qq] : ask_y[j]) {
            auto[x, y] = qrys[qq];
            while (i > sx) {
                i--;
                line l = {rg[i][j - 1], f[i][j]};
                while (!deq.empty() && deq.back().a <= l.a) {
                    deq.pop_back();
                }
                while (deq.size() >= 2 && intersect(deq.end()[-2], deq.back(), l)) {
                    deq.pop_back();
                }
                deq.emplace_back(l);
            }
            int lo = 0, hi = int(deq.size()) - 1;
            while (lo + 1 < hi) {
                int mid = (lo + hi) >> 1;
                if (intersect(deq[mid], deq[mid + 1], points_y[j] - y)) {
                    lo = mid;
                } else {
                    hi = mid;
                }
            }
            for (int k = lo; k <= hi; ++k) {
                chmax(ans[qq], deq[k](points_y[j] - y));
            }
        }
    }

    for (int i = 0; i < Q; ++i) {
        std::cout << ans[i] << '\n';
    }

    return 0;
}
#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...