Cod sursa(job #3135893)

Utilizator dandragosDan Dragos dandragos Data 4 iunie 2023 17:19:12
Problema Secv8 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.12 kb
#include <bits/stdc++.h>

using namespace std;

ifstream in("secv8.in");
ofstream out("secv8.out");

const int MAX_N = 250000;

typedef struct Treap* Tree;
typedef pair<Tree, Tree> PTT;
Tree NIL;

struct Treap
{
    int size, lazy, priority, value;
    Tree left, right;
    Treap(int val) : size(1), lazy(0), priority(rand()), value(val), left(NIL), right(NIL) {}
};

// Divizează treap-ul în două subtreap-uri în funcție de poziția dată
PTT split(Tree t, int pos);

// Unifică două treap-uri
Tree merge(Tree a, Tree b);

// Recalculează dimensiunea unui treap
void recalculateSize(Tree t);

// Aplică propagarea leneșă într-un treap
void applyLazyPropagation(Tree t);

// Afișează elementele unui treap în ordine
void printTree(Tree t);

// Inserează un element în treap la o anumită poziție
Tree insertElement(Tree root, int val, int pos);

// Inversează subsecvența unui treap între două poziții
Tree reverseSubarray(Tree root, int x, int y);

// Șterge subsecvența unui treap între două poziții
Tree deleteSubarray(Tree root, int x, int y);

// Obține elementul de la o anumită poziție din treap
int getElem(Tree t, int pos);

int main()
{
    NIL = new Treap(0);
    NIL->size = 0;
    NIL->left = NIL->right = NIL;
    srand(time(0));

    Tree root = NIL;
    int N, useless;
    in >> N >> useless;
    while (N--) {
        char ch;
        int x, y;
        in >> ch >> x;
        if (ch == 'I') // Inserare
            in >> y,
            root = insertElement(root, y, x);
        else if (ch == 'A') // Obținere element
            out << getElem(root, x) << '\n';
        else if (ch == 'R') // Inversare subsecvență
            in >> y,
            root = reverseSubarray(root, x, y);
        else if (ch == 'D') // Ștergere subsecvență
            in >> y,
            root = deleteSubarray(root, x, y);
    }
    printTree(root);
    return 0;
}

PTT split(Tree t, int pos) {
    applyLazyPropagation(t);

    if (pos > t->size)
        return {t, NIL};

    if (pos == t->left->size + 1) {
        PTT ans = {t->left, t};
        t->left = NIL;
        recalculateSize(t);
        return ans;
    }
    if (pos <= t->left->size) {
        PTT ans = split(t->left, pos);
        t->left = NIL;
        recalculateSize(t);
        return {ans.first, merge(ans.second, t)};
    }
    PTT ans = split(t->right, pos - t->left->size - 1);
    t->right = NIL;
    recalculateSize(t);
    return {merge(t, ans.first), ans.second};
}

Tree merge(Tree a, Tree b)
{
    applyLazyPropagation(a);
    applyLazyPropagation(b);

    if (a == NIL)
        return b;
    if (b == NIL)
        return a;

    if (a->priority > b->priority) {
        a->right = merge(a->right, b);
        recalculateSize(a);
        return a;
    }
    b->left = merge(a, b->left);
    recalculateSize(b);
    return b;
}

void recalculateSize(Tree t)
{
    t->size = t->left->size + t->right->size + (t != NIL);
}

void applyLazyPropagation(Tree t)
{
    if (t->lazy) {
        swap(t->left, t->right);
        t->left->lazy ^= 1;
        t->right->lazy ^= 1;
    }
    t->lazy = 0;
}

void printTree(Tree t) {
    applyLazyPropagation(t);
    if (t == NIL)
        return;
    printTree(t->left);
    out << t->value << ' ';
    printTree(t->right);
}

Tree insertElement(Tree root, int val, int pos)
{
    Tree tr = new Treap(val);
    PTT pr = split(root, pos);
    return merge(merge(pr.first, tr), pr.second);
}

Tree reverseSubarray(Tree root, int x, int y)
{
    PTT p1 = split(root, y + 1);
    PTT p2 = split(p1.first, x);
    p2.second->lazy ^= 1;
    return merge(merge(p2.first, p2.second), p1.second);
}

Tree deleteSubarray(Tree root, int x, int y)
{
    PTT p1 = split(root, y + 1);
    PTT p2 = split(p1.first, x);
    return merge(p2.first, p1.second);
}

int getElem(Tree t, int pos)
{
    applyLazyPropagation(t);
    if (t->left->size == pos - 1)
        return t->value;
    if (t->left->size >= pos)
        return getElem(t->left, pos);
    return getElem(t->right, pos - t->left->size - 1);
}