【CSP-J 2021】 小熊的果篮

【CSP-J 2021】 小熊的果篮 解题报告

1 题目链接

洛谷P7912

2 题目大意

题目名称:小熊的果篮
题目大意:

(这…)
小熊的水果店里摆放着一排 n n n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1 , 2 , … , n 1, 2, \ldots, n 1,2,,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里,具体方法是:每次都把每一个“块”中最左边的水果同时挑出,组成一个果篮。重复这一操作,直至水果用完。注意,每次挑完一个果篮后,“块”可能会发生变化。比如两个苹果“块”之间的唯一桔子被挑走后,两个苹果“块”就变成了一个“块”。请帮小熊计算每个果篮里包含的水果。
题目大意:简称题目本身
这除了原文谁说得清啊喂。

3 解法分析

正解似乎有相当多种做法,例如: O ( n n ) O(n\sqrt{n}) O(nn ) O ( n ) O(n) O(n) O ( n log ⁡ n ) O(n\log n) O(nlogn)等等。
线段树和珂朵莉树过分了啊
显然一眼丁真,链表。然鹅…
《你没 30 m i n 30min 30min调不出来系列》
模拟赛就写这东西写挂了(打死我也不会说我最后输出 1 1 1 n n n水到了 10 10 10分)。
这里说一个 O ( n log ⁡ n ) O(n\log n) O(nlogn) 500 b y t e 500byte 500byte蒟蒻专属做法罢。

(以上是废话)
首先,要知道set这个奆容器。
与链表不同,我们可以开两个set分别用于存放01的下标
显然,对于每一行输出,我们只需在两个set旋转跳跃即可。
为了方便模拟,我们想到了异或运算,也就是^。对于一个01,只需a ^ 1即可转换。
因此,set开成set st[2]会节约许多转换过程
那么,这道题基本思路已经梳理完了。
细节见代码。

4 AC Code

#include 
#define N 200007
using namespace std;

int n, a[N];
set <int> st[2];//细节减码量

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]),
		st[a[i]].insert(i);//每一个都压入set
	}
	st[0].insert(1e9);//以判断当前是否已经遍历完
	st[1].insert(1e9);//同上
	while (*st[0].begin() != 1e9 || *st[1].begin() != 1e9/*0与1都没有遍历完*/) {
		for (int i = min(*st[0].begin(), *st[1].begin());//初始化为两边最小,即为开头
				i != 1e9; i = *st[a[i] ^ 1].lower_bound(i)) {//不断二分更新
			printf("%d ", i);//直接输出
			st[a[i]].erase(i);//细节删除
		}
		puts("");//细节换行
	}
	return 0;
}//蒟蒻的奇妙码风

5 瞎说

建议各位有机会的话写一写链表。
真锻炼模拟能力

你可能感兴趣的:(CCF,题解,算法,c++,容器)