#pragma GCC optimize(2) // 累了就吸点氧吧~ #include using namespace std; const int N = 200010; struct Node { // 块 int st, ed, th; }; int n, a[N]; queue q1, q2; bool used[N]; // 记录是否被取出 int main() { // 加快读入 ios::sync_with_stdio(false), cin.tie(0); cin >> n; memset(a, -1, sizeof a); for (int i = 1; i <= n; i++) cin >> a[i]; // 很经典的代码 for (int i = 2, x = 1; i <= n; i++) if (a[i] != a[i + 1]) q1.push({x, i, a[i]}), x = i + 1; // 把连续一段相同的元素合成一个块 // 取没拉倒 while (n) { while (q1.size()) { // 有块存在 Node k = q1.front(); // k这个块 q1.pop(); // 1111 00 1111 :取两轮后,第1块和第3块就会连上 while (used[k.st]) k.st++; // 跳过块中已取过的水果 if (k.st > k.ed) continue; // 取没了,这个块就放过,看看下一个块吧 printf("%d ", k.st); // 如果没有取没,那就取这个号的水果 n--; // 取走一个水果 used[k.st] = 1; // 标识已取出 k.st++; // 不是最后一个,取完后块的开始位置 if (k.st > k.ed) continue; // 取没了,这个块就放过,看看下一个块吧 q2.push(k); // 先将缩减的小块存到 q2 里,因为可能会有些区间连上了,需要进行合并 } puts(""); // 1111 00 1111 :取两轮后,第1块和第3块就会连上 // 完成合并任务 while (q2.size()) { Node k = q2.front(); q2.pop(); while (q2.size()) { Node x = q2.front(); if (x.th == k.th) { // 能合并就合并 k.ed = x.ed; q2.pop(); } else break; } q1.push(k); // 丢回 q1 里 } } return 0; }