P7912 [CSP-J 2021] 小熊的果篮 题解
题目解析
题目还是很好理解的,就是给你一个非零即一的序列,让你每一轮在每一个块里拿出最前面的水果,然后输出
有很多人用都是链表的做法,但是对于我这种不会链表的怎么办呢?
很容易发现,无论有没有合并,01都是交替拿的,而且拿到的一定比现在的下标大
可以把所有的0放在一个有序数组里,所有1放在一个有序数组里,然后从小到大交替拿就可以
可以用set维护有序数组,而查找就用二分,时间复杂度\(O(nlogn)\)
代码如下
#include <bits/stdc++.h>
using namespace std;
constexpr int inf = 2e5 + 2;
set<int> x, y;
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
x.insert(inf), y.insert(inf); // 防止空set错误
int c;
for (int i = 1; i <= n; i++) {
cin >> c;
if (!c)
x.insert(i);
else
y.insert(i);
}
int p = 1, now = 0;
if (*x.begin() < *y.begin()) p = 0; // 一开始要从小开始拿
while ((!p && x.size() > 1) || (p && y.size() > 1)) {
if (!p) {
now = *x.upper_bound(now); // 二分
if (now == inf) {
cout << '\n';
now = 0;
if (*x.begin() < *y.begin())
p = 0;
else
p = 1;
continue;
} else {
cout << now << " ";
x.erase(now);
p = !p;
}
} else {
now = *y.upper_bound(now);
if (now == inf) {
cout << '\n';
now = 0;
if (*x.begin() < *y.begin())
p = 0;
else
p = 1;
continue;
} else {
cout << now << " ";
y.erase(now);
p = !p;
}
}
}
cout << '\n';
for (int i : x) // 输出剩余的数
if (i != inf) cout << i << '\n';
for (int i : y)
if (i != inf) cout << i << '\n';
return 0;
}
听懂?点赞?

浙公网安备 33010602011771号