有一個 1..N 的排列,機器人每次將當前最小的數通過「區間翻轉」移到最前面。輸出該數翻轉前的位置(1-based)。
利用 Splay 树(伸展树)維護序列,支持區間翻轉與刪除操作:
rev[x] ^= 1 交換左右孩子,下傳時遞歸翻轉。struct Node { int ch[2], fa, sz; bool rev; } tr[MAXN];
int root, tot;
void pushup(int x) { tr[x].sz = tr[tr[x].ch[0]].sz + tr[tr[x].ch[1]].sz + 1; }
void pushrev(int x) { if (!x) return; swap(tr[x].ch[0], tr[x].ch[1]); tr[x].rev ^= 1; }
void pushdown(int x) { if (tr[x].rev) { pushrev(tr[x].ch[0]); pushrev(tr[x].ch[1]); tr[x].rev = 0; } }
bool isRoot(int x) { return tr[tr[x].fa].ch[0] != x && tr[tr[x].fa].ch[1] != x; }
void rotate(int x) { /* 單旋實現 */ }
void splay(int x, int goal) { /* 伸展操作,含 pushdown 下傳 */ }
void build(int &x, int l, int r, int fa) { /* 遞歸建平衡樹 */ }
int main() {
int n; while (cin >> n, n) {
// 讀入數值,記錄原始索引,按值排序
// 建樹
for (int i = 1; i < n; ++i) {
splay(id[i], 0); // 將第 i 小的數伸展到根
pushrev(tr[root].ch[0]); // 翻轉左子樹
cout << tr[tr[root].ch[0]].sz + i << ' '; // 輸出位置
// 刪除根
}
cout << n << '\n';
}
}
本題展示了 Splay 树作為「序列維護」數據結構的強大能力:隱式鍵值 + 延遲標記 可高效支持區間翻轉、查詢排名、刪除等操作。雙旋優化是 AC 關鍵。