#include using namespace std; mt19937 rng_priority; struct node { int l, r; int y; int cnt; int value; int max_subtree; node (const int value_) : value(value_), max_subtree(value), y(rng_priority()), l(-1), r(-1), cnt(1) {} }; struct treap_manager { vector pool; int subtree (const int v) const { return v == -1 ? 0 : pool[v].cnt; } int maxsub (const int v) const { return v == -1 ? numeric_limits::min() : pool[v].max_subtree; } void recalc (const int v) { if (v != -1) { pool[v].cnt = subtree(pool[v].l) + 1 + subtree(pool[v].r); pool[v].max_subtree = max({maxsub(pool[v].l), pool[v].value, maxsub(pool[v].r)}); } } int merge(int l, int m, int r) { return merge(merge(l, m), r); } /// налево k самых маленьких ключей 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 - 1 - subtree(pool[t].l)); pool[t].r = l; recalc(t); return pair(t, r); } else { // pool[t].x >= x; tie(l, r) = split(pool[t].l, k); pool[t].l = r; recalc(t); return pair(l, t); } } int merge (int l, int r) { if (l == -1) return r; if (r == -1) return l; if (pool[l].y > pool[r].y) { pool[l].r = merge(pool[l].r, r); recalc(l); return l; } else { pool[r].l = merge(l, pool[r].l); recalc(r); return r; } } int add_node (const int value) { const int ver = int(pool.size()); pool.push_back(node(value)); return ver; } 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); const int ans = merge(l, ver, r); return ans; } /// возвращает идентификатор дерева после удаления ключа x int remove_at_pos (const int tree, const int pos) { int l, m, r; tie(l, m) = split(tree, pos); /// в l получилось pos значений /// в m -- оставшиеся tie(m, r) = split(m, 1); /// в m теперь ключ x return merge(l, r); } /// [left, right) в 0-индексации int move_to_front (const int tree, int left, int right) { int l, m, r; /// l --- [0, left) /// m --- [left, right) /// r --- [right, n) tie(l, m) = split(tree, left); /// после этого: l --- [0, left), m -- [left, n) tie(m, r) = split(m, right - left); return merge(m, l, r); } /// найти k-тый по возрастанию ключ в поддереве root и вернуть его int get_kth_values (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_values(pool[root].l, k); /// k >= subtree(pool[root].l) + 1; /// от 0 до subtree(root) - subtree(pool[root].l) - 1 == subtree(pool[root].r); return get_kth_values(pool[root].r, k - subtree(pool[root].l) - 1); } void print_values (ostream &cout, const int root) { if (root == -1) return; print_values(cout, pool[root].l); cout << pool[root].value << ' '; print_values(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); // treap.print_values(cerr, root); // cerr << endl; for (int i = 0; i < m; i++) { int l, r; cin >> l >> r; --l; root = treap.move_to_front(root, l, r); } treap.print_values(cout, root); cout << endl; } int main() { // ifstream fin("movetofront.in"); // ofstream fout("movetofront.out"); solve(cin, cout); }