Implicit Treap Implementation for Advanced Sequence Operations

Complex sequence manipulations such as range additions, reversals, cyclic shifts, insertions, deletions, and minimum queries can be efficiently handled using an Implicit Treap (also known as a non-rotating Treap or FHQ Treap). By leveraging split and merge operations based on subtree sizes, specific intervals can be isolated and modifications applied directly to the root of the extracted subtree.

To support range updates without degrading time complexity, two lazy propagation tags are required: one for reversing the interval and another for applying a uniform increment. Propagation must occur before any structural changes like split or merge to ensure child nodes receive pending updates correctly.

The propagation function applies both tags sequentially. If the reverse flag is active, the left and right children of the current node are swapped, and the flag is pushed down to both subtrees. If an increment value exists, it is added to the node's base value, the subtree minimum, and the child's pending increment tags, resetting the current node's tag to zero.

#include <iostream>
#include <string>
#include <random>
#include <algorithm>

using namespace std;

const long long INF = 1e18;
const int MAX_NODES = 200005;

struct TreapNode {
    long long value;
    long long weight;
    long long size;
    long long minimum;
    int left_child;
    int right_child;
    bool flip_tag;
    long long add_tag;
} pool[MAX_NODES];

int node_idx = 0;
int root_id = 0;
mt19937 rng(42);

int build_node(long long v) {
    ++node_idx;
    pool[node_idx].value = v;
    pool[node_idx].weight = rng();
    pool[node_idx].size = 1;
    pool[node_idx].minimum = v;
    pool[node_idx].left_child = pool[node_idx].right_child = 0;
    pool[node_idx].flip_tag = false;
    pool[node_idx].add_tag = 0;
    return node_idx;
}

void refresh(int u) {
    if (!u) return;
    pool[u].size = pool[pool[u].left_child].size + pool[pool[u].right_child].size + 1;
    pool[u].minimum = pool[u].value;
    if (pool[u].left_child) pool[u].minimum = min(pool[u].minimum, pool[pool[u].left_child].minimum);
    if (pool[u].right_child) pool[u].minimum = min(pool[u].minimum, pool[pool[u].right_child].minimum);
}

void push_inc(int u, long long v) {
    if (!u) return;
    pool[u].value += v;
    pool[u].minimum += v;
    pool[u].add_tag += v;
}

void push_flip(int u) {
    if (!u) return;
    swap(pool[u].left_child, pool[u].right_child);
    pool[u].flip_tag ^= true;
}

void propagate(int u) {
    if (!u) return;
    if (pool[u].flip_tag) {
        push_flip(pool[u].left_child);
        push_flip(pool[u].right_child);
        pool[u].flip_tag = false;
    }
    if (pool[u].add_tag) {
        push_inc(pool[u].left_child, pool[u].add_tag);
        push_inc(pool[u].right_child, pool[u].add_tag);
        pool[u].add_tag = 0;
    }
}

void split_tree(int u, int k, int &L, int &R) {
    if (!u) {
        L = R = 0;
        return;
    }
    propagate(u);
    int left_sz = pool[pool[u].left_child].size;
    if (left_sz < k) {
        L = u;
        split_tree(pool[u].right_child, k - left_sz - 1, pool[u].right_child, R);
    } else {
        R = u;
        split_tree(pool[u].left_child, k, L, pool[u].left_child);
    }
    refresh(u);
}

int merge_tree(int L, int R) {
    if (!L || !R) return L | R;
    propagate(L);
    propagate(R);
    if (pool[L].weight < pool[R].weight) {
        pool[L].right_child = merge_tree(pool[L].right_child, R);
        refresh(L);
        return L;
    } else {
        pool[R].left_child = merge_tree(L, pool[R].left_child);
        refresh(R);
        return R;
    }
}

void range_add(int x, int y, long long z) {
    int A, B, C;
    split_tree(root_id, y, B, C);
    split_tree(B, x - 1, A, B);
    push_inc(B, z);
    root_id = merge_tree(merge_tree(A, B), C);
}

void range_reverse(int x, int y) {
    int A, B, C;
    split_tree(root_id, y, B, C);
    split_tree(B, x - 1, A, B);
    push_flip(B);
    root_id = merge_tree(merge_tree(A, B), C);
}

void range_rotate(int x, int y, long long z) {
    int A, B, C, D;
    z %= (y - x + 1);
    if (z == 0) return;
    split_tree(root_id, y, C, D);
    split_tree(C, x - 1, A, C);
    split_tree(C, (y - x + 1) - z, B, C);
    root_id = merge_tree(merge_tree(merge_tree(A, C), B), D);
}

void insert_at(int pos, long long v) {
    int A, B;
    split_tree(root_id, pos, A, B);
    root_id = merge_tree(merge_tree(A, build_node(v)), B);
}

void delete_at(int pos) {
    int A, B, C;
    split_tree(root_id, pos - 1, A, B);
    split_tree(B, 1, B, C);
    root_id = merge_tree(A, C);
}

long long query_min(int x, int y) {
    int A, B, C;
    split_tree(root_id, y, B, C);
    split_tree(B, x - 1, A, B);
    long long res = pool[B].minimum;
    root_id = merge_tree(merge_tree(A, B), C);
    return res;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, q;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        long long v;
        cin >> v;
        insert_at(i - 1, v);
    }
    cin >> q;
    while (q--) {
        string op;
        cin >> op;
        if (op == "ADD") {
            long long x, y, z;
            cin >> x >> y >> z;
            range_add(x, y, z);
        } else if (op == "REVERSE") {
            long long x, y;
            cin >> x >> y;
            range_reverse(x, y);
        } else if (op == "REVOLVE") {
            long long x, y, z;
            cin >> x >> y >> z;
            range_rotate(x, y, z);
        } else if (op == "INSERT") {
            long long pos, v;
            cin >> pos >> v;
            insert_at(pos, v);
        } else if (op == "DELETE") {
            long long pos;
            cin >> pos;
            delete_at(pos);
        } else if (op == "MIN") {
            long long x, y;
            cin >> x >> y;
            cout << query_min(x, y) << "\n";
        }
    }
    return 0;
}

Tags: Implicit Treap Lazy Propagation Sequence Manipulation Data Structures C++

Posted on Sat, 11 Jul 2026 16:35:27 +0000 by phui_99