제출 #1353202

#제출 시각아이디문제언어결과실행 시간메모리
1353202cnam9새 집 (APIO18_new_home)C++20
100 / 100
1744 ms146024 KiB
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#define inline inline __attribute__((always_inline))

using namespace std;

constexpr int N = 3e5 + 5;
constexpr int INF = 1e9;

struct Store {
    int x, type, l, r;
};

Store stores[N];
vector<int> positions[N];
int xoi[N];
int toi[N];

pair<int, int> real_queries[N];
vector<pair<int, int>> queries[N];
vector<pair<int, bool>> updates[N];

// sexagesicuaternary tree
class FastSet {
    using u64 = unsigned long long;
    int n;
    vector<vector<u64>> tree;

public:
    void assign(int n) {
        this->n = n;
        tree.clear();
        if (n == 0) return;

        int sz = n;
        while (true) {
            int new_sz = (sz + 63) >> 6;
            tree.emplace_back(new_sz, 0ull); // empty set
            if (new_sz == 1) break;
            sz = new_sz;
        }
    }

    void insert(int i) {
        if (i < 0 || i >= n) return;
        for (size_t h = 0; h < tree.size(); h++) {
            u64 mask = 1ull << (i & 63);
            if (tree[h][i >> 6] & mask) break; 
            tree[h][i >> 6] |= mask;
            i >>= 6;
        }
    }

    void erase(int i) {
        if (i < 0 || i >= n) return;
        for (size_t h = 0; h < tree.size(); h++) {
            tree[h][i >> 6] &= ~(1ull << (i & 63));
            if (tree[h][i >> 6]) break;
            i >>= 6;
        }
    }

    inline void set(int i, bool value) {
        if (value)
            insert(i);
        else
            erase(i);
    }

    // lower_bound
    int next(int i) const {
        for (size_t h = 0; h < tree.size(); h++) {
            int u = i >> 6;
            if (u >= tree[h].size()) break;
            
            u64 mask = tree[h][u] & (~0ull << (i & 63));
            if (!mask) {
                i = (i >> 6) + 1;
                continue;
            }
            i = (u << 6) + __builtin_ctzll(mask);
            for (int g = (int)h - 1; g >= 0; g--) {
                i = (i << 6) + __builtin_ctzll(tree[g][i]);
            }
            return (i < n) ? i : n;
        }
        return n;
    }

    // --upper_bound
    int prev(int i) const {
        for (size_t h = 0; h < tree.size(); h++) {
            int u = i >> 6;
            if (u < 0) break;
            
            u64 mask = tree[h][u];
            if ((i & 63) != 63) {
                mask &= (1ull << ((i & 63) + 1)) - 1;
            }
            
            if (!mask) {
                i = (i >> 6) - 1;
                continue;
            }
            i = (u << 6) + (63 - __builtin_clzll(mask));
            for (int g = (int)h - 1; g >= 0; g--) {
                i = (i << 6) + (63 - __builtin_clzll(tree[g][i]));
            }
            return i;
        }
        return -1;
    }

    inline bool operator[](int i) const {
        return (tree[0][i >> 6] >> (i & 63)) & 1;
    }

    inline int size() const {
        return n;
    }
};

FastSet fs[N];

struct SegmentTree {
    int n;
    int tree[N * 2];

    struct DEPQ {
        priority_queue<int> pq;
        priority_queue<int> to_delete;

        int query() {
            while (!to_delete.empty() && to_delete.top() == pq.top()) {
                to_delete.pop();
                pq.pop();
            }
            return pq.empty() ? -INF : pq.top();
        }

        void insert(int value) {
            pq.push(value);
        }

        void erase(int value) {
            to_delete.push(value);
        }
    } leaves[N];

    void init(int n) {
        this->n = n;
        fill(tree + 1, tree + 2 * n, -INF);
    }

    inline void build(int i) {
        int value = leaves[i].query();
        for (tree[i += n] = value; i > 1; i >>= 1) {
            tree[i >> 1] = max(tree[i], tree[i ^ 1]);
        }
    }

    inline void insert(int i, int value) {
        leaves[i].insert(value);
        build(i);
    }

    inline void erase(int i, int value) {
        leaves[i].erase(value);
        build(i);
    }

    inline int query(int l, int r) {
        int res = -INF;
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) res = max(res, tree[l++]);
            if (r & 1) res = max(res, tree[--r]);
        }
        return res;
    }
} Ltree, Rtree;

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // freopen("input.txt", "r", stdin);

    int n, k, q;
    cin >> n >> k >> q;

    for (int i = 0; i < n; i++) {
        auto &[x, type, l, r] = stores[i];
        cin >> x >> type >> l >> r;
    }
    sort(stores, stores + n, [](const Store &s, const Store &t) {
        return s.x < t.x;
    });
    for (int i = 0; i < n; i++) {
        positions[stores[i].type].push_back(i);
    }

    for (int i = 0; i < q; i++) {
        auto &[x, t] = real_queries[i];
        cin >> x >> t;

        xoi[i] = x;
        toi[i] = t;
    }

    sort(xoi, xoi + q);
    int X = unique(xoi, xoi + q) - xoi;

    sort(toi, toi + q);
    int T = unique(toi, toi + q) - toi;

    for (int i = 0; i < q; i++) {
        auto [x, t] = real_queries[i];
        x = lower_bound(xoi, xoi + X, x) - xoi;
        t = lower_bound(toi, toi + T, t) - toi;
        queries[t].emplace_back(x, i);
    }

    for (int i = 0; i < n; i++) {
        auto [x, type, l, r] = stores[i];
        l = lower_bound(toi, toi + T, l) - toi;
        r = upper_bound(toi, toi + T, r) - toi;

        updates[l].emplace_back(i, true);
        updates[r].emplace_back(i, false);
    }

    for (int type = 1; type <= k; type++) {
        for (int it = 0; it < positions[type].size(); it++) {
            int i = positions[type][it];
            stores[i].l = it;
        }
    }

    Ltree.init(X + 1);
    Rtree.init(X + 1);

    for (int t = 1; t <= k; t++) {
        Ltree.insert(0, INF);
        Rtree.insert(0, INF);
    }

    for (int type = 1; type <= k; type++) {
        fs[type].assign(positions[type].size());
    }

    auto insert_store = [&](int type, int pos) {
        int x = stores[positions[type][pos]].x;

        int L = fs[type].prev(pos);
        int R = fs[type].next(pos);
        L = L < 0 ? -INF : stores[positions[type][L]].x;
        R = R >= fs[type].size() ? INF : stores[positions[type][R]].x;

        int M = upper_bound(xoi, xoi + X, (L + R) / 2) - xoi;
        int Ml = upper_bound(xoi, xoi + X, (L + x) / 2) - xoi;
        int Mr = upper_bound(xoi, xoi + X, (x + R) / 2) - xoi;

        Ltree.erase(M, -L);
        Rtree.erase(M, R);
        Ltree.insert(Ml, -L);
        Rtree.insert(Ml, x);
        Ltree.insert(Mr, -x);
        Rtree.insert(Mr, R);

        fs[type].insert(pos);
    };

    auto erase_store = [&](int type, int pos) {
        int x = stores[positions[type][pos]].x;

        fs[type].erase(pos);

        int L = fs[type].prev(pos);
        int R = fs[type].next(pos);
        L = L < 0 ? -INF : stores[positions[type][L]].x;
        R = R >= fs[type].size() ? INF : stores[positions[type][R]].x;

        int M = upper_bound(xoi, xoi + X, (L + R) / 2) - xoi;
        int Ml = upper_bound(xoi, xoi + X, (L + x) / 2) - xoi;
        int Mr = upper_bound(xoi, xoi + X, (x + R) / 2) - xoi;

        Ltree.erase(Ml, -L);
        Rtree.erase(Ml, x);
        Ltree.erase(Mr, -x);
        Rtree.erase(Mr, R);
        Ltree.insert(M, -L);
        Rtree.insert(M, R);
    };

    for (int t = 0; t <= T; t++) {
        for (auto [i, insert] : updates[t]) {
            auto [x, type, l, r] = stores[i];

            if (insert) {
                insert_store(type, l);
            } else {
                erase_store(type, l);
            }
        }

        for (auto [Xmap, i] : queries[t]) {
            int x = xoi[Xmap];
            int &ans = real_queries[i].first;

            ans = max(Ltree.query(Xmap + 1, X + 1) + x,
                      Rtree.query(0, Xmap + 1) - x);
        }
    }

    for (int t = T - 1; t >= 0; t--) {
        for (auto it = updates[t + 1].rbegin(); it != updates[t + 1].rend(); ++it) {
            auto [i, erase] = *it;
            auto [x, type, l, r] = stores[i];

            if (erase) {
                erase_store(type, l);
            } else {
                insert_store(type, l);
            }
        }

        for (auto [Xmap, i] : queries[t]) {
            int x = xoi[Xmap];
            int &ans = real_queries[i].first;
            ans = max(ans,
                  max(Ltree.query(Xmap + 1, X + 1) + x,
                      Rtree.query(0, Xmap + 1) - x));
        }
    }

    for (int i = 0; i < q; i++) {
        int ans = real_queries[i].first;
        cout << (ans >= (int)1e8 ? -1 : ans) << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...