<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

187. Twist and whirl - want to cheat
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
input: standard input
output: standard output



A well-known sharper I*** invented a new way to swindle people. There are N thimbles on the table, and there is a small ball with the number under each of them. The balls are numbered with numbers from 1 to N from left to right. At one operation I*** changes the order of some subsequence of successive thimbles to the opposite. Your task is to find the order of numbers (from left to right) in sequence after all of his manipulations. The total number of manipulations is M.

Input
The first line contains two integer numbers N and M (1<=N<=130000, 1<=M<=2000) separated by a space. Each of the following M lines contains two integer numbers Pi, Qi (1<=Pi<=Qi<=N) - positions of the leftmost and rightmost thimbles in rotated sequence.

Output
Output the sequence of N numbers - the numbers of balls in the thimbles from left to right.

Sample test(s)

Input
Test #1
5 2
1 3
4 5

Test #2
5 2
1 4
2 5

Output
Test #1
3 2 1 5 4

Test #2
4 5 1 2 3
Author:	Michael R. Mirzayanov
Resource:	ACM International Collegiate Programming Contest 2003-2004
North-Eastern European Region, Southern Subregion
Date:	2003 October, 9

<|response|>
1. Abridged problem statement  
Given an initial sequence of thimbles numbered 1 through N, perform M operations. Each operation specifies indices l and r, and you must reverse the subarray from position l to position r (inclusive). After all operations, output the final sequence.

2. Key observations  
- A single reverse of a subarray of length L takes O(L) time if done naively on an array. In the worst case, repeating M times gives O(N·M), which can be up to 2.6·10^8 element moves (too slow under 0.25 s in C++).  
- We need a data structure that supports:  
  • splitting the sequence at an arbitrary position in O(log N)  
  • merging two sequences in O(log N)  
  • applying “reverse” to an entire subsequence in O(1) (lazy propagation)  
- An implicit treap (Cartesian tree by position) with a lazy “reverse” flag satisfies these requirements.  

3. Full solution approach  
We represent the sequence as an implicit treap, where the in-order traversal of the treap nodes yields the current sequence. Each node stores:  
  • val: the current element value (initially 1…N)  
  • prior: a random priority for heap ordering  
  • size: size of the subtree rooted at this node  
  • rev: a boolean lazy flag indicating that this subtree should be reversed  
  • left, right: child pointers  

We maintain these invariants:  
  - The tree is a min- or max-heap by priority.  
  - In-order traversal corresponds to the sequence order.  
  - `size` is always correct for each subtree.  
  - If `rev` is true at a node, its children are logically swapped, and the flag should be pushed down when accessing that node.  

Key operations:  
  • update_size(node): recalculate node->size = 1 + size(left) + size(right).  
  • push(node): if node->rev is true, swap(node->left, node->right), propagate rev to children, clear node->rev.  
  • split(node, k): split the treap into (L, R) so that L contains the first k elements (by in-order) and R contains the rest.  
  • merge(A, B): merge two treaps A and B assuming all elements in A come before those in B in in-order.  

To reverse the subarray [l,r]:  
  1. Split root into (A, BC) at k = l−1.  
  2. Split BC into (B, C) at k = r−l+1.  
  3. Toggle B->rev.  
  4. Merge back: root = merge(A, merge(B, C)).  

Each split/merge takes O(log N) on average, so total is O((N + M) log N), which is efficient for N up to 130 000 and M up to 2000.

4. C++ implementation with detailed comments  
```cpp
#include <bits/stdc++.h>
using namespace std;

// Implicit treap node
struct Node {
    int val;        // the sequence value
    int prior;      // random priority
    int size;       // size of subtree
    bool rev;       // lazy reverse flag
    Node *l, *r;    // children

    Node(int v)
        : val(v), prior((rand()<<16) ^ rand()), size(1),
          rev(false), l(nullptr), r(nullptr) {}
};

// Return size of subtree or 0 if null
int getSize(Node* t) {
    return t ? t->size : 0;
}

// Recalculate size from children
void updateSize(Node* t) {
    if (!t) return;
    t->size = 1 + getSize(t->l) + getSize(t->r);
}

// Push down the reverse flag
void push(Node* t) {
    if (t && t->rev) {
        // swap children
        swap(t->l, t->r);
        // propagate flag
        if (t->l) t->l->rev = !t->l->rev;
        if (t->r) t->r->rev = !t->r->rev;
        // clear flag
        t->rev = false;
    }
}

// Split treap 't' into (l, r) so that l has first 'k' elements
void split(Node* t, int k, Node*& l, Node*& r) {
    if (!t) {
        l = r = nullptr;
        return;
    }
    push(t);
    int leftSize = getSize(t->l);
    if (k <= leftSize) {
        // target split is entirely in left subtree
        split(t->l, k, l, t->l);
        r = t;
    } else {
        // split goes into right subtree
        split(t->r, k - leftSize - 1, t->r, r);
        l = t;
    }
    updateSize(t);
}

// Merge two treaps a and b, where all keys in a come before b
Node* merge(Node* a, Node* b) {
    if (!a || !b) return a ? a : b;
    push(a);
    push(b);
    if (a->prior > b->prior) {
        a->r = merge(a->r, b);
        updateSize(a);
        return a;
    } else {
        b->l = merge(a, b->l);
        updateSize(b);
        return b;
    }
}

// In-order traversal to collect the sequence
void inorder(Node* t, vector<int>& out) {
    if (!t) return;
    push(t);
    inorder(t->l, out);
    out.push_back(t->val);
    inorder(t->r, out);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    srand(time(nullptr));
    int N, M;
    cin >> N >> M;

    // Build initial treap with values 1..N by successive merges
    Node* root = nullptr;
    for(int i = 1; i <= N; i++){
        Node* node = new Node(i);
        root = merge(root, node);
    }

    // Process each reverse operation
    for(int i = 0; i < M; i++){
        int l, r;
        cin >> l >> r;
        // split into A=[1..l-1] and BC=[l..N]
        Node *A, *BC;
        split(root, l-1, A, BC);
        // split BC into B=[l..r] and C=[r+1..N]
        Node *B, *C;
        split(BC, r-l+1, B, C);
        // mark B to be reversed
        if (B) B->rev = !B->rev;
        // reassemble
        root = merge( merge(A, B), C );
    }

    // Output final sequence
    vector<int> result;
    result.reserve(N);
    inorder(root, result);
    for(int x : result) {
        cout << x << ' ';
    }
    cout << "\n";

    return 0;
}
```

5. Python implementation with detailed comments  
```python
import sys
import threading
import random

sys.setrecursionlimit(1 << 25)

def main():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    m = int(next(it))

    # Node of the implicit treap
    class Node:
        __slots__ = ('val','prior','size','rev','l','r')
        def __init__(self, v):
            self.val = v
            self.prior = random.randrange(1 << 30)
            self.size = 1
            self.rev = False
            self.l = None
            self.r = None

    def get_size(t):
        return t.size if t else 0

    def update(t):
        if not t:
            return
        t.size = 1 + get_size(t.l) + get_size(t.r)

    def push(t):
        if t and t.rev:
            # swap children
            t.l, t.r = t.r, t.l
            # toggle flags
            if t.l:
                t.l.rev = not t.l.rev
            if t.r:
                t.r.rev = not t.r.rev
            t.rev = False

    # Split into (left, right) where left has first k elements
    def split(t, k):
        if not t:
            return (None, None)
        push(t)
        if get_size(t.l) >= k:
            left, t.l = split(t.l, k)
            update(t)
            return (left, t)
        else:
            t.r, right = split(t.r, k - get_size(t.l) - 1)
            update(t)
            return (t, right)

    # Merge two treaps a and b
    def merge(a, b):
        if not a or not b:
            return a or b
        push(a)
        push(b)
        if a.prior > b.prior:
            a.r = merge(a.r, b)
            update(a)
            return a
        else:
            b.l = merge(a, b.l)
            update(b)
            return b

    # Build initial treap by merging nodes 1..n
    root = None
    for v in range(1, n+1):
        node = Node(v)
        root = merge(root, node)

    # Perform m reversals
    for _ in range(m):
        l = int(next(it))
        r = int(next(it))
        A, BC = split(root, l-1)
        B, C  = split(BC, r-l+1)
        if B:
            B.rev = not B.rev
        root = merge(merge(A, B), C)

    # In-order traversal to collect result
    ans = []
    def inorder(t):
        if not t:
            return
        push(t)
        inorder(t.l)
        ans.append(str(t.val))
        inorder(t.r)

    inorder(root)
    print(' '.join(ans))

if __name__ == "__main__":
    threading.Thread(target=main).start()
```

Explanation of the main parts:
- We use an implicit treap: a randomized balanced BST where the “key” is the position in the sequence (implicit by subtree sizes).  
- `split` partitions the treap by position, `merge` joins two treaps.  
- To reverse a subarray, we split out that segment, toggle its lazy `rev` flag (which will swap children when needed), then merge everything back.  
- Final in-order traversal prints the resulting sequence in O(N).