Cod sursa(job #3357289)

Utilizator TincaMateiTinca Matei TincaMatei Data 8 iunie 2026 15:42:42
Problema Secv8 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.5 kb
#include <bits/stdc++.h>
#include <cassert>

template<typename K>
struct SplayTreeNode {
    K key;
    uint8_t flip = 0;
    int st = 1;

    SplayTreeNode<K>* child[2] = {0};
    SplayTreeNode<K>* parent = NULL;

    ~SplayTreeNode() {
        delete child[0];
        delete child[1];
        child[0] = child[1] = parent = NULL;
    }

    SplayTreeNode(K k) : key(k) {}

    void push_lazy() {
        if (flip) {
            std::swap(child[0], child[1]);
            if (child[0]) child[0]->flip ^= 1;
            if (child[1]) child[1]->flip ^= 1;
        }
        flip = 0;
    }

    void attach(int side, SplayTreeNode* new_ch) {
        if (new_ch)
            new_ch->parent = this;
        child[side] = new_ch;
    }

    void detach() {
        assert(parent);
        int s = side();
        parent->child[s] = NULL;
        parent = NULL;
    }

    void recompute() {
        st = 1;
        if (child[0]) st += child[0]->st;
        if (child[1]) st += child[1]->st;
    }

    SplayTreeNode(K k, SplayTreeNode<K>* left, SplayTreeNode<K>* right) {
        key = k;
        st = 1;

        attach(0, left);
        attach(1, right);
        recompute();
    }

    int side() {
        return parent->child[1] == this;
    }
};

template<typename K>
void debug(SplayTreeNode<K>* T, int spaces = 0) {
    if (spaces >= 16) return;


    std::string tab = std::string(spaces, ' ');
    if (T == NULL) {
        std::cerr << tab << "-\n";
        return;
    }
    std::cerr << tab << T->key << " " << T->st << " " << T << " " << "parent: " << T->parent << " " << "Flip: " << (int)T->flip <<  "\n";

    debug(T->child[0], spaces + 4);
    debug(T->child[1], spaces + 4);
}

// This will TLE for sure lmao.
template<typename T>
SplayTreeNode<T>* rotate_up(SplayTreeNode<T>* x) {
    if (!x->parent) return x;

    int sz = 6;
    std::array<SplayTreeNode<T>*, 6> target, to, rec;
    std::array<int, 6> side;
    SplayTreeNode<T>* old_root;
    
    auto p = x->parent;     
    if (p->parent)
        p->parent->push_lazy();
    p->push_lazy();
    x->push_lazy();
    int s = x->side();

    int flip = s;

    if (!x->parent->parent) { // Zig
        sz = 4;
        auto A = x->child[0 ^ s], B = x->child[1 ^ s], C = p->child[1 ^ s];
        target = {x, x, p, p}; side = {0, 1, 0, 1}; to = {A, p, B, C}; rec = {p, x};
        old_root = p;
    } else {
        auto q = p->parent;
        old_root = q;
        int s2 = p->side();

        if (s == s2) { // zig-zig
            auto A = x->child[0 ^ s], B = x->child[1 ^ s], C = p->child[1 ^ s], D = q->child[1 ^ s];
            target = {x, x, p, p, q, q}; side = {0, 1, 0, 1, 0, 1}; to = {A, p, B, q, C, D}; rec = {q, p, x};
        } else {
            flip ^= 1;
            auto A = p->child[0 ^ flip], B = x->child[0 ^ flip], C = x->child[1 ^ flip], D = q->child[1 ^ flip];
            target = {x, x, p, p, q, q}; side = {0, 1, 0, 1, 0, 1}; to = {p, q, A, B, C, D}; rec = {q, p, x};
        }
    }

    // std::cerr << "Before rotation\n";
    // debug(old_root, 4);

    if (old_root->parent) {
        auto pq = old_root->parent;
        int s = old_root->side();
        pq->attach(s, x);
    } else {
        x->parent = NULL;
    }


    for (int i = 0; i < sz; i++)
        target[i]->attach(side[i] ^ flip, to[i]);
    for (int i = 0; i < sz / 2; i++)
        rec[i]->recompute();

    // std::cerr << "After rotation\n";
    // debug(x, 4);

    return x;
}

template<typename K>
SplayTreeNode<K>* splay(SplayTreeNode<K>* T) {
    while (T->parent)
        T = rotate_up<K>(T);
    return T;
}

template<typename K>
SplayTreeNode<K>* find(SplayTreeNode<K>* T, int pos) {
    T->push_lazy();
    int lsz = 0;
    if (T->child[0]) lsz = T->child[0]->st;

    if (pos <= lsz) {
        return find(T->child[0], pos);
    } else if (1 + lsz < pos) {
        return find(T->child[1], pos - 1 - lsz);
    } else {
        return splay(T);
    }
}

template<typename K>
SplayTreeNode<K>* splay_right(SplayTreeNode<K>* T) {
    T->push_lazy();
    if (T->child[1])
        return splay_right(T->child[1]);
    else
        return splay(T);
}

template<typename K>
std::pair<SplayTreeNode<K>*, SplayTreeNode<K>*> split(SplayTreeNode<K>* T, int pos) {
    if (T == NULL) return {T, T};
    T->push_lazy();

    if (pos <= 0) return {NULL, T};
    if (pos > T->st) return {T, NULL};


    // std::cerr << "Calling find on (with element " << pos << "):\n";
    // debug(T, 4);
    T = find(T, pos);
    auto Q = T->child[1];
    if (Q) Q->detach();
    T->recompute();
    return {T, Q};
}

template<typename K>
SplayTreeNode<K>* join(SplayTreeNode<K>* L, SplayTreeNode<K>* R) {
    if (!L) return R;
    L = splay_right(L);
    L->attach(1, R);
    L->recompute();
    return L;
}

template<typename K>
SplayTreeNode<K>* insert(SplayTreeNode<K>* T, int pos, K k) {
    auto [L, R] = split(T, pos - 1);
    auto n = new SplayTreeNode<K>(k, L, R);
    return n;
}

template<typename K>
SplayTreeNode<K>* erase(SplayTreeNode<K>* T, int l, int r) {
    auto [_M, R] = split(T, r);
    auto [L, M] = split(_M, l - 1);
    delete(M);
    return join(L, R);
}

template<typename K>
SplayTreeNode<K>* reverse(SplayTreeNode<K>* T, int l, int r) {
    auto [_M, R] = split(T, r);
    auto [L, M] = split(_M, l - 1);
    M->flip ^= 1;
    return join(L, join(M, R));
}

template<typename K>
void inorder(SplayTreeNode<K>* T, std::ofstream& fout) {
    if (T == NULL) return;
    T->push_lazy();

    inorder(T->child[0], fout);
    fout << T->key << " ";
    inorder(T->child[1], fout);
}

int main() {

    std::ifstream fin("secv8.in");
    std::ofstream fout("secv8.out");

    SplayTreeNode<int>* T = NULL;
    
    int Q, x;
    fin >> Q >> x;

    // T = insert(T, 1, 1);
    // T = insert(T, 2, 2);
    // T = insert(T, 3, 3);
    // T = reverse(T, 2, 3);

    // std::cerr << "After reverse\n";
    // debug(T, 0);

    // std::cerr << "INSERT:\n";
    // T = insert(T, 4, 4);

    // std::cerr << "After insert:\n";
    // debug(T, 0);


    while (Q--) {
        char c;
        fin >> c;

        if (c == 'I') {
            int k, e;
            fin >> k >> e;
            T = insert(T, k, e);
        } else if (c == 'A') {
            int k;
            fin >> k;
            T = find(T, k);
            fout << T->key << "\n";
        } else if (c == 'R') {
            int l, r;
            fin >> l >> r;
            T = reverse(T, l, r);
        } else {
            int l, r;
            fin >> l >> r;
            T = erase(T, l, r);
        }

        // std::cerr << "Operation:\n";
        // debug(T);
    }

    inorder(T, fout);


    delete T;

    return 0;
}