Cod sursa(job #3357290)

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

class InParser {
private:
	FILE *fin;
	char *buff;
	int sp;


public:
	char read_ch() {
		++sp;
		if (sp == 4096) {
			sp = 0;
			fread(buff, 1, 4096, fin);
		}
		return buff[sp];
	}

	InParser(const char* nume) {
		fin = fopen(nume, "r");
		buff = new char[4096]();
		sp = 4095;
	}
	
	InParser& operator >> (int &n) {
		char c;
		while (!isdigit(c = read_ch()) && c != '-');
		int sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
	
	InParser& operator >> (long long &n) {
		char c;
		n = 0;
		while (!isdigit(c = read_ch()) && c != '-');
		long long sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
};


class OutParser {
private:
    FILE *fout;
    char *buff;
    int sp;
 
    void write_ch(char ch) {
        if (sp == 50000) {
            fwrite(buff, 1, 50000, fout);
            sp = 0;
            buff[sp++] = ch;
        } else {
            buff[sp++] = ch;
        }
    }
 
 
public:
    OutParser(const char* name) {
        fout = fopen(name, "w");
        buff = new char[50000]();
        sp = 0;
    }
    ~OutParser() {
        fwrite(buff, 1, sp, fout);
        fclose(fout);
    }
 
    OutParser& operator << (int vu32) {
        if (vu32 <= 9) {
            write_ch(vu32 + '0');
        } else {
            (*this) << (vu32 / 10);
            write_ch(vu32 % 10 + '0');
        }
        return *this;
    }
 
    OutParser& operator << (long long vu64) {
        if (vu64 <= 9) {
            write_ch(vu64 + '0');
        } else {
            (*this) << (vu64 / 10);
            write_ch(vu64 % 10 + '0');
        }
        return *this;
    }
 
    OutParser& operator << (char ch) {
        write_ch(ch);
        return *this;
    }
    OutParser& operator << (const char *ch) {
        while (*ch) {
            write_ch(*ch);
            ++ch;
        }
        return *this;
    }
};

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, OutParser& 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");
    InParser fin("secv8.in");
    OutParser 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.read_ch();
        while (!isalpha(c)) c = fin.read_ch();

        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;
}