Submission #1332313

#TimeUsernameProblemLanguageResultExecution timeMemory
1332313MisterReaperSweeping (JOI20_sweeping)C++20
100 / 100
3920 ms52144 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;
}

constexpr int inf = int(1E9) + 5;

#ifdef LOCAL
    std::mt19937 rng(23);
#else
    std::random_device rd;
    std::mt19937 rng(rd());
#endif

struct node {
    int wei = rng();
    int siz = 0;
    int x = -1;
    int y = -1;
    int mny = inf;
    int mxy = 0;
    int lzx = -1;
    int lzy = -1;
    int lc = 0;
    int rc = 0;
    int par = 0;
    node() {}
    node(int x_, int y_) {
        x = x_;
        y = y_;
        siz = 1;
        mny = y_;
        mxy = y_;
    }
};

std::vector<node> tree = {{}};

int new_node(node nd = node()) {
    tree.emplace_back(nd);
    return int(tree.size()) - 1;
}
int new_node(int X, int Y) {
    return new_node(node(X, Y));
}

void modify(int v, int x, int y) {
    if (!v) {
        return;
    }
    chmax(tree[v].x, x);
    chmax(tree[v].lzx, x);
    chmax(tree[v].y, y);
    chmax(tree[v].lzy, y);
    chmax(tree[v].mny, y);
    chmax(tree[v].mxy, y);
}

void push(int v) {
    if (!v) {
        return;
    }
    modify(tree[v].lc, tree[v].lzx, tree[v].lzy);
    modify(tree[v].rc, tree[v].lzx, tree[v].lzy);
    tree[v].lzx = tree[v].lzy = -1;
}

void pull(int v) {
    if (!v) {
        return;
    }
    tree[v].siz = tree[tree[v].lc].siz + tree[tree[v].rc].siz + 1;
    tree[v].mny = std::min({tree[v].y, tree[tree[v].lc].mny, tree[tree[v].rc].mny});
    tree[v].mxy = std::max({tree[v].y, tree[tree[v].lc].mxy, tree[tree[v].rc].mxy});
    tree[tree[v].lc].par = v;
    tree[tree[v].rc].par = v;
    if (tree[v].lc) {
        assert(std::max(tree[v].lzx, tree[tree[v].lc].x) <= tree[v].x);
    }
    if (tree[v].rc) {
        assert(std::max(tree[v].lzx, tree[tree[v].rc].x) >= tree[v].x);
    }
}

void debug_node(int v, int lzx = 0, int lzy = 0, std::string ps = "") {
    if (!v) {
        return;
    }
    lzx = std::max(lzx, tree[v].lzx);
    lzy = std::max(lzy, tree[v].lzy);
    debug_node(tree[v].lc, lzx, lzy, ps + ":: ");
    std::cerr << ps << std::max(lzx, tree[v].x) << ' ' << std::max(lzy, tree[v].y) << '\n';
    debug_node(tree[v].rc, lzx, lzy, ps + ":: ");
}

void merge(int& v, int lv, int rv) {
    if (!lv || !rv) {
        v = (lv ? lv : rv);
        return;
    }
    push(lv), push(rv);
    if (tree[lv].wei > tree[rv].wei) {
        merge(tree[lv].rc, tree[lv].rc, rv);
        v = lv;
    } else {
        merge(tree[rv].lc, lv, tree[rv].lc);
        v = rv;
    }
    // debug(__LINE__);
    pull(v);
    // debug(__LINE__);
}

// x[i]<=k
void split_by_x(int v, int& lv, int& rv, int k) {
    if (!v) {
        lv = rv = 0;
        return;
    }
    push(v);
    if (tree[v].x <= k) {
        split_by_x(tree[v].rc, tree[v].rc, rv, k);
        lv = v;
    } else {
        split_by_x(tree[v].lc, lv, tree[v].lc, k);
        rv = v;
    }
    // debug(__LINE__);
    pull(lv), pull(rv);
    // debug(__LINE__);
}

void super_merge(int& v, int x, int y) {
    if (!x || !y) {
        v = (x ? x : y);
        return;
    }
    push(x), push(y);
    if (tree[x].wei < tree[y].wei) {
        std::swap(x, y);
    } 
    int ly, ry;
    split_by_x(y, ly, ry, tree[x].x);
    super_merge(tree[x].lc, tree[x].lc, ly);
    super_merge(tree[x].rc, tree[x].rc, ry);
    v = x;
    // debug(__LINE__);
    pull(v);
    // debug(__LINE__);
}

// y[i]<=k
void split_by_y(int v, int& lv, int& rv, int k) {
    if (!v) {
        lv = rv = 0;
        return;
    }
    if (tree[v].mny > k) {
        lv = 0;
        rv = v;
        return;
    }
    if (tree[v].mxy <= k) {
        lv = v;
        rv = 0;
        return;
    }
    push(v);
    int lx, rx;
    split_by_y(tree[v].lc, lx, rx, k);
    int ly, ry;
    split_by_y(tree[v].rc, ly, ry, k);
    if (tree[v].y <= k) {
        tree[v].lc = lx;
        tree[v].rc = ly;
        int w;
        merge(w, rx, ry);
        lv = v;
        rv = w;
    } else {
        tree[v].lc = rx;
        tree[v].rc = ry;
        int w;
        merge(w, lx, ly);
        lv = w;
        rv = v;
    }
    // debug(__LINE__);
    pull(lv);
    // debug(__LINE__);
    // debug_node(rv);
    pull(rv);
    // debug(__LINE__);
}

std::pair<int, int> get_value(int v) {
    int d = 0;
    int x = tree[v].x, y = tree[v].y;
    while (tree[v].par != 0) {
        v = tree[v].par;
        chmax(x, tree[v].lzx);
        chmax(y, tree[v].lzy);
        d += 1;
    }
    assert(d <= 100);
    return {x, y};
}

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

    int root = 0;

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

    std::vector<int> ids;
    for (int i = 0; i < M; ++i) {
        int X, Y;
        std::cin >> X >> Y;
        int nd = new_node(X, Y);
        ids.emplace_back(nd);
        int lv, rv;
        split_by_x(root, lv, rv, X);
        merge(root, lv, nd);
        merge(root, root, rv);
    }

    while (Q--) {
        int TP;
        std::cin >> TP;
        // debug(TP);
        if (TP == 1) {
            int P;
            std::cin >> P;
            --P;
            auto[x, y] = get_value(ids[P]);
            std::cout << x << ' ' << y << '\n';
        } else if (TP == 2) {
            int X;
            std::cin >> X;
            int lv, rv;
            split_by_y(root, lv, rv, X);
            modify(lv, N - X, 0);
            super_merge(root, lv, rv);
        } else if (TP == 3) {
            int X;
            std::cin >> X;
            int lv, rv;
            split_by_x(root, lv, rv, X);
            modify(lv, 0, N - X);
            merge(root, lv, rv);
        } else {
            int X, Y;
            std::cin >> X >> Y;
            int nd = new_node(X, Y);
            ids.emplace_back(nd);
            int lv, rv;
            split_by_x(root, lv, rv, X);
            merge(root, lv, nd);
            merge(root, root, rv);
        }
    }

    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...