#include using namespace std; mt19937 rng_priority; struct node { int l, r; int y; int cnt; int value; node (const int value_) : value(value_), y(rng_priority()), l(-1), r(-1), cnt(1) {} }; struct treap_manager { vector pool; int add_node(const int value) { const int ans = int(pool.size()); pool.push_back(node(value)); return ans; } int subtree (const int v) { /// if (v == -1) /// return 0; /// else /// return pool[v].cnt; return v == -1 ? 0 : pool[v].cnt; } void recalc(const int v) { if (v != -1) pool[v].cnt = subtree(pool[v].l) + 1 + subtree(pool[v].r); } int merge(int l, int m, int r) { return merge(merge(l, m), r); } pair split (const int t, const int k) { if (t == -1) return pair(-1, -1); int l, r; /// if (pool[t].x < xs) if (subtree(pool[t].l) < k) { /// Так МОЖНО написать, но не нужно. // const int mem = pool[t].r; // pool[t].r = -1; // tie(l, r) = split(mem, x); // pool[t].r = l; tie(l, r) = split(pool[t].r, k - subtree(pool[t].l) - 1); /// Поддеревья l и r --- всё хорошо (cnt-шки посчитаны правильно). pool[t].r = l; /// Слишком умные студенты :) pool[t].cnt -= subtree(r); return pair(t, r); } else { // pool[t].x >= x; /// pair p = split(pool[t].l, k); /// l = p.first; /// r = p.second; tie(l, r) = split(pool[t].l, k); pool[t].l = r; pool[t].cnt -= subtree(l); return pair(l, t); } } int merge (int l, int r) { if (l == -1) return r; if (r == -1) return l; const int total_size = subtree(l) + subtree(r); if (pool[l].y > pool[r].y) { const int sr = subtree(r); pool[l].r = merge(pool[l].r, r); /// А вот это работает! pool[l].cnt += sr; // pool[l].cnt = total_size; return l; } else { const int sl = subtree(l); pool[r].l = merge(l, pool[r].l); /// А вот это работает! pool[r].cnt += sl; // pool[r].cnt = total_size; return r; } } int move_to_front (const int tree, const int left, const int right) { int l, m, r; tie(l, m) = split(tree, left); tie(m, r) = split(m, right - left); return merge(m, l, r); } int insert_at_pos (const int tree, const int pos, const int value) { const int ver = add_node(value); int l, r; tie(l, r) = split(tree, pos); return merge(l, ver, r); } /// возвращает идентификатор дерева после удаления ключа x int remove_at_pos (const int tree, const int pos) { int l, m, r; tie(l, m) = split(tree, pos); /// Важно, что 1! tie(m, r) = split(m, 1); return merge(l, r); } /// в 0-индексации, то есть 0 <= k < subtree(root); int get_kth_value (const int root, const int k) { assert(0 <= k && k < subtree(root)); if (k == subtree(pool[root].l)) return pool[root].value; if (k < subtree(pool[root].l)) return get_kth_value(pool[root].l, k); /// k >= subtree(pool[root].l) + 1; return get_kth_value(pool[root].r, k - subtree(pool[root].l) - 1); } void print_tree (ostream &cout, const int root) { if (root == -1) return; print_tree(cout, pool[root].l); cout << pool[root].value << ' '; print_tree(cout, pool[root].r); } }; void solve(istream &cin, ostream &cout) { int n, m; cin >> n >> m; treap_manager treap; int root = -1; for (int i = 1; i <= n; i++) root = treap.insert_at_pos(root, treap.subtree(root), i); for (int i = 0; i < m; i++) { int l, r; cin >> l >> r; --l; root = treap.move_to_front(root, l, r); } treap.print_tree(cout, root); cout << endl; } int main() { // ifstream fin("input.txt"); // ofstream fout("output.txt"); // solve(fin, fout); solve(cin, cout); }