【CF1100B】Build a Contest

题意

你有 $n$ 道题和一个 $k$,每一题的难度在 $1$ 和 $k$ 之间。

每凑足了 $k$ 个不同难度的新题目,就必须举办一次比赛,包含 $1$ 至 $k$ 难度的题目各一道。

当然,已经在举办的比赛用过的题目将作废,无法重复使用。

如果你出了第 $i$ 题后要举办一次比赛了,那么 $f(i)=1$,否则 $f(i)=0$

最后,请让 $i$ 从 $1$ 到 $n$ 按顺序输出所有的 $f(i)$,中间不用空格分开。

$1 le n,k le 10^5$

解析

显然,我们可以求出可以举办的比赛次数,就是 $1$ 至 $k$ 中各个难度出现的题数的最小值。

那我们可以求一个东西:我们如果要举办第 $x$ 次比赛,那么需要知道的是当前每一个难度的题目数是否不小于 $x.$

这个东西很好求,我们只需要在线处理每一个难度题目数出现的次数。

因为每一个数不大于 $10^5$,可以开一个桶记录出现相同难度的次数。

我们定义数组 $cnt$ 为桶,$sum$ 记录答案,$sum_i$ 即为出第 $i$ 次比赛前已经有的题目数量。

那么,对于第 $p$ 个数 $x$,让 $cnt_x$ 加一,$sum_{cnt_x}=p$ 即可。

最后,让 $x$ 从 $1$ 推到 $min{cnt_i}$,用数组 $ans$ 记录答案序列,即让 $ans_{sum_x}=1$

然后输出即可。

参考代码

#include <cstdio>
#define N 100010

int k, n, a, cnt[N], sum[N], ans[N], minn = 1e9; inline int min(int a, int b){ return a < b ? a : b; } int main(){ scanf("%d%d", &k, &n); for(int i=1; i<=n; i++){ scanf("%d", &a); sum[++cnt[a]] = i; }
for(int i=1; i<=k; i++) minn = min(minn, cnt[i]); for(int i=1; i<=minn; i++) ans[sum[i]]++; for(int i=1; i<=n; i++) printf("%d", ans[i]); return 0; }
原文地址:https://www.cnblogs.com/zengpeichen/p/11520012.html