<|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.

271. Book Pile
time limit per test: 0.25 sec.
memory limit per test: 65536 KB
input: standard
output: standard



There is a pile of N books on the table. Two types of operations are performed over this pile:
- a book is added to the top of the pile,
- top K books are rotated. If there are less than K books on the table, the whole pile is rotated.
First operation is denoted as ADD(S) where S is the name of the book, and the second operations is denoted as ROTATE.
The maximum number of books is no more than 40000. All book names are non-empty sequences of no more than 3 capital Latin letters. The names of the books can be non-unique.

Input
The first line of input file contains 3 integer numbers N, M, K (0 <= N <= 40000; 0 <= M <= 100000; 0 <= K <= 40000). The following N lines are the names of the books in the pile before performing any operations. The book names are given in order from top book to bottom. Each of the following M lines contains the operation description.

Output
Output the sequence of books names in the pile after performing all operations. First line corresponds to the top book.

Sample test(s)

Input
2 3 2
A
B
ADD(C)
ROTATE
ADD(D)

Output
D
A
C
B
Author:	Michael R. Mirzayanov
Resource:	ACM ICPC 2004-2005, NEERC, Southern Subregional Contest
Date:	Saratov, October 7, 2004

<|response|>
1. Abridged Problem Statement  
You have a pile (stack) of books, initially N books given from top to bottom. You then perform M operations of two types:  
- **ADD(S)**: push a new book named S onto the top of the pile.  
- **ROTATE**: reverse the order of the top K books (if fewer than K books remain, reverse the whole pile).  
After all operations, output the final pile from top to bottom.  
Constraints:  
• 0 ≤ N ≤ 40000, 0 ≤ M ≤ 100000, 0 ≤ K ≤ 40000  
• Book names are 1–3 uppercase letters; duplicates allowed.  

2. Key Observations  
- A naïve array or list reversal of the top K books per ROTATE would cost O(K) each, leading to O(M·K) worst-case (up to 4·10^9), too slow.  
- We need O(1) or amortized O(1) per operation.  
- Notice that K is fixed throughout, so we only ever reverse a prefix of size “up to K.”  
- We can keep the top K books in one data structure (“prefix”) and the remaining books below in another (“suffix”), maintaining the invariant that prefix.size() ≤ K.  
- By storing a boolean flag rev on the prefix, we can “reverse” it logically in O(1) by flipping the flag, and push/pop at its ends in O(1) even under reversal.  
- Any time prefix grows beyond K (after an ADD), we move its logical back element into the front of suffix, keeping prefix.size() ≤ K.  

3. Full Solution Approach  
Maintain two deques of strings, prefix and suffix, plus a boolean rev indicating whether prefix is logically reversed:  
Initialization:  
  - Read the N initial books into a single deque all_books (front = top).  
  - Move elements from the back of all_books into the front of suffix until all_books.size() ≤ K.  
  - Let prefix = all_books (remaining ≤ K books), and set rev = false.  

Operations:  
  - ADD(S):  
      • To push S onto the top of the pile, we insert S into the logical front of prefix:  
          if rev==false, prefix.push_front(S); else prefix.push_back(S).  
      • If prefix.size() > K, we pop its logical back (if rev==false pop_back(), else pop_front()) and push that book to the front of suffix.  
  - ROTATE:  
      • Flip rev = !rev. This logically reverses prefix in O(1).  

Final Output:  
  - First output prefix in correct order: if rev==false, iterate from front to back; else from back to front.  
  - Then output suffix from front to back (always in normal order).  

All operations are O(1) amortized, so total O(N+M).  

4. C++ Implementation with Detailed Comments  

```cpp
#include <bits/stdc++.h>
using namespace std;

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

    int N, M, K;
    cin >> N >> M >> K;

    // Read initial pile: top at front of all_books
    deque<string> all_books;
    for (int i = 0; i < N; i++) {
        string name;
        cin >> name;
        all_books.push_back(name);
    }

    // Split into prefix (up to K books) and suffix (the rest)
    deque<string> suffix;
    while ((int)all_books.size() > K) {
        // move bottom of all_books (back) to top of suffix (front)
        suffix.push_front(all_books.back());
        all_books.pop_back();
    }
    deque<string> prefix = move(all_books);

    // rev = false means prefix in natural order (front=top); 
    // if rev=true, prefix is logically reversed.
    bool rev = false;

    auto prefix_push_front = [&](const string &s) {
        if (!rev) prefix.push_front(s);
        else       prefix.push_back(s);
    };
    auto prefix_pop_back = [&]() {
        if (!rev) {
            string x = prefix.back(); 
            prefix.pop_back(); 
            return x;
        } else {
            string x = prefix.front(); 
            prefix.pop_front(); 
            return x;
        }
    };

    // Process M operations
    for (int i = 0; i < M; i++) {
        string op;
        cin >> op;
        if (op[0] == 'A') {
            // ADD(S): extract S between '(' and ')'
            string S = op.substr(4, op.size() - 5);
            // insert at logical front of prefix
            prefix_push_front(S);
            // if prefix grew beyond K, move its logical back to suffix front
            if ((int)prefix.size() > K) {
                string moved = prefix_pop_back();
                suffix.push_front(moved);
            }
        } else {
            // ROTATE: logically reverse the prefix
            rev = !rev;
        }
    }

    // Output final pile: prefix (with rev) then suffix
    // 1) prefix
    if (!rev) {
        for (auto &book : prefix) {
            cout << book << "\n";
        }
    } else {
        for (auto it = prefix.rbegin(); it != prefix.rend(); ++it) {
            cout << *it << "\n";
        }
    }
    // 2) suffix
    for (auto &book : suffix) {
        cout << book << "\n";
    }

    return 0;
}
```

5. Python Implementation with Detailed Comments  

```python
import sys
from collections import deque

def main():
    data = sys.stdin.read().split()
    it = iter(data)
    N = int(next(it))
    M = int(next(it))
    K = int(next(it))

    # Read initial pile: top at front
    all_books = deque()
    for _ in range(N):
        all_books.append(next(it))

    # Split off the bottom (size-K) into suffix
    suffix = deque()
    while len(all_books) > K:
        suffix.appendleft(all_books.pop())
    prefix = all_books  # up to K books
    rev = False         # prefix normal if False, reversed if True

    # Helpers to treat prefix with logical reversal
    def push_front(s):
        if not rev:
            prefix.appendleft(s)
        else:
            prefix.append(s)
    def pop_back():
        if not rev:
            return prefix.pop()
        else:
            return prefix.popleft()

    # Process operations
    for _ in range(M):
        op = next(it)
        if op[0] == 'A':   # ADD(...)
            # extract book name
            name = op[4:-1]
            push_front(name)
            # keep prefix size ≤ K
            if len(prefix) > K:
                moved = pop_back()
                suffix.appendleft(moved)
        else:  # ROTATE
            rev = not rev

    # Output final pile
    out = []
    if not rev:
        out.extend(prefix)
    else:
        out.extend(reversed(prefix))
    out.extend(suffix)

    sys.stdout.write("\n".join(out))

if __name__ == "__main__":
    main()
```

Explanation of Key Steps:  
- We never pay O(K) per ROTATE; flipping the boolean rev reverses our view in O(1).  
- By keeping prefix.size() ≤ K, every ADD that overflows prefix does one O(1) move into suffix.  
- Final printing takes O(N) to traverse prefix+suffix once.  
This yields O(N + M) time and O(N) extra memory, comfortably within the problem limits.