94 lines
2.7 KiB
C++
94 lines
2.7 KiB
C++
|
|
#include <bits/stdc++.h>
|
|||
|
|
using namespace std;
|
|||
|
|
#define endl '\n'
|
|||
|
|
/*
|
|||
|
|
主要注释说明:
|
|||
|
|
数据结构:
|
|||
|
|
Node结构体:表示一个连续的相同水果块
|
|||
|
|
q和q2队列:分别用于存储当前块和临时合并的块
|
|||
|
|
used数组:标记水果是否已被取出
|
|||
|
|
主要步骤:
|
|||
|
|
初始化:将连续相同的水果合并成块
|
|||
|
|
循环处理:
|
|||
|
|
取出每个块的最左水果
|
|||
|
|
将剩余部分放入临时队列
|
|||
|
|
合并相邻的相同类型块
|
|||
|
|
将合并后的块放回主队列
|
|||
|
|
关键优化:
|
|||
|
|
使用队列管理块,避免频繁的数组操作
|
|||
|
|
通过合并相邻块减少处理次数
|
|||
|
|
使用标记数组避免重复处理
|
|||
|
|
这个实现通过块的管理和合并,高效地处理了水果的挑出过程,比之前的实现更加优化。
|
|||
|
|
*/
|
|||
|
|
const int N = 200010;
|
|||
|
|
struct Node { // 定义块的结构体
|
|||
|
|
int st, ed, th; // st:块的起始位置,ed:块的结束位置,th:块的类型(0或1)
|
|||
|
|
} f, x, ad;
|
|||
|
|
|
|||
|
|
int n, cnt, t[N]; // n:水果总数,cnt:剩余水果数,t[]:存储水果序列
|
|||
|
|
queue<Node> q, q2; // q:当前待处理的块队列,q2:临时存储合并后的块
|
|||
|
|
bool used[N]; // 记录每个位置的水果是否已被取出
|
|||
|
|
|
|||
|
|
int main() {
|
|||
|
|
cin >> n;
|
|||
|
|
for (int i = 1; i <= n; i++)
|
|||
|
|
cin >> t[i];
|
|||
|
|
|
|||
|
|
// 在序列末尾添加一个与最后一个水果不同的值,方便处理边界情况
|
|||
|
|
t[n + 1] = !t[n];
|
|||
|
|
|
|||
|
|
// 将连续相同的水果合并成块
|
|||
|
|
for (int i = 2, si = 1; i <= n + 1; i++) {
|
|||
|
|
if (t[i] != t[i - 1]) {
|
|||
|
|
// 当遇到不同水果时,将之前的连续段作为一个块加入队列
|
|||
|
|
q.push((Node){si, i - 1, t[si]}), si = i;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cnt = n; // 初始化剩余水果数
|
|||
|
|
while (cnt) { // 当还有水果未被取出时继续循环
|
|||
|
|
// 处理当前所有块
|
|||
|
|
while (q.size()) {
|
|||
|
|
f = q.front();
|
|||
|
|
q.pop();
|
|||
|
|
|
|||
|
|
// 跳过已经被取出的水果
|
|||
|
|
while (used[f.st] && f.st <= f.ed)
|
|||
|
|
f.st++;
|
|||
|
|
|
|||
|
|
if (f.st > f.ed)
|
|||
|
|
continue; // 如果块已空则跳过
|
|||
|
|
|
|||
|
|
// 输出并标记当前块的最左水果
|
|||
|
|
printf("%d ", f.st), cnt--;
|
|||
|
|
used[f.st] = 1;
|
|||
|
|
|
|||
|
|
if (f.ed == f.st)
|
|||
|
|
continue; // 如果块中只有一个水果,取完后跳过
|
|||
|
|
|
|||
|
|
// 将剩余部分加入临时队列
|
|||
|
|
f.st++;
|
|||
|
|
q2.push(f);
|
|||
|
|
}
|
|||
|
|
cout << endl; // 一个果篮处理完毕,换行
|
|||
|
|
|
|||
|
|
// 合并相邻的相同类型块
|
|||
|
|
while (q2.size()) {
|
|||
|
|
ad = q2.front();
|
|||
|
|
q2.pop();
|
|||
|
|
|
|||
|
|
// 尝试合并后续相同类型的块
|
|||
|
|
while (q2.size()) {
|
|||
|
|
x = q2.front();
|
|||
|
|
if (x.th == ad.th) { // 如果类型相同则合并
|
|||
|
|
ad.ed = x.ed;
|
|||
|
|
q2.pop();
|
|||
|
|
} else
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
q.push(ad); // 将合并后的块放回主队列
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|