F - Usual Color Ball Problems
Problem Statement
You are given positive integers $N$, $M$, $K$, and a sequence of positive integers of length $N$, $(C_1, C_2, \ldots, C_N)$. For each $r = 0, 1, 2, \ldots, N-1$, print the answer to the following problem.
There is a sequence of $N$ colored balls. For $i = 1, 2, \ldots, N$, the color of the $i$-th ball from the beginning of the sequence is $C_i$. Additionally, there are $M$ empty boxes numbered $1$ to $M$.
Determine the total number of balls in the boxes after performing the following steps.
First, perform the following operation $r$ times.
- Move the frontmost ball in the sequence to the end of the sequence.
Then, repeat the following operation as long as at least one ball remains in the sequence.
- If there is a box that already contains at least one but fewer than $K$ balls of the same color as the frontmost ball in the sequence, put the frontmost ball into that box.
- If there is no such box,
- If there is an empty box, put the frontmost ball into the one with the smallest box number.
- If there are no empty boxes, eat the frontmost ball without putting it into any box.
Constraints
- All input values are integers.
- $1 \leq N \leq 2 \times 10^5$
- $1 \leq M, K \leq N$
- $1 \leq C_i \leq N$
Input
The input is given from Standard Input in the following format:
$N$ $M$ $K$
$C_1$ $C_2$ $\ldots$ $C_N$
Output
Print the answer $X_r$ to the problem for each $r = 0, 1, 2, \ldots, N-1$ over $N$ lines as follows:
$X_0$
$X_1$
$\vdots$
$X_{N-1}$
Sample Input 1
7 2 2
1 2 3 5 2 5 4
Sample Output 1
3
3
3
4
4
3
2
For example, let us explain the procedure for $r = 1$. First, perform the operation "Move the frontmost ball in the sequence to the end of the sequence" once, and the sequence of ball colors becomes $(2, 3, 5, 2, 5, 4, 1)$. Then, proceed with the operation of putting balls into boxes as follows:
- First operation: The color of the frontmost ball is $2$. There is no box with at least one but fewer than two balls of color $2$, so put the frontmost ball into the empty box with the smallest box number, box $1$.
- Second operation: The color of the frontmost ball is $3$. There is no box with at least one but fewer than two balls of color $3$, so put the frontmost ball into the empty box with the smallest box number, box $2$.
- Third operation: The color of the frontmost ball is $5$. There is no box with at least one but fewer than two balls of color $5$ and no empty boxes, so eat the frontmost ball.
- Fourth operation: The color of the frontmost ball is $2$. There is a box, box $1$, with at least one but fewer than two balls of color $2$, so put the frontmost ball into box $1$.
- Fifth operation: The color of the frontmost ball is $5$. There is no box with at least one but fewer than two balls of color $5$ and no empty boxes, so eat the frontmost ball.
- Sixth operation: The color of the frontmost ball is $4$. There is no box with at least one but fewer than two balls of color $4$ and no empty boxes, so eat the frontmost ball.
- Seventh operation: The color of the frontmost ball is $1$. There is no box with at least one but fewer than two balls of color $1$ and no empty boxes, so eat the frontmost ball.
The final total number of balls in the boxes is $3$, so the answer to the problem for $r = 1$ is $3$.
Sample Input 2
20 5 4
20 2 20 2 7 3 11 20 3 8 7 9 1 11 8 20 2 18 11 18
Sample Output 2
14
14
14
14
13
13
13
11
8
9
9
11
13
14
14
14
14
14
14
13
解题思路
这题不难,最大的坑点是同一种颜色的球可以用多个盒子装,昨晚一直以为一种颜色只能用一个盒子,然后一直搁那 WA 8。
首先由于涉及到循环移动,所以直接破环成链,把数组拷贝一份拼接到后面,即 $c_{i+n} = c_i, \, i \in [0, n-1]$。求答案的时候只需枚举左端点 $i, \, i \in [0, n-1]$,然后对依次对区间 $[i, i+n-1]$ 按照题意进行模拟就好了。很显然需要用到数据结构来优化模拟的过程。
先求出在单个区间 $[i, i+n-1]$ 中能装的球的数量。事先统计长度为 $n$ 的序列中每种颜色 $i$ 的球的数量用 $s_i$ 来表示,设置一个指针 $j=i$ 从左往右遍历,哈希表 $mp[i]$ 表示 $i \sim j$ 中已装入颜色为 $i$ 的球的数量,$sz$ 表示已用盒子的数量,$\text{ret}$ 表示所有盒子装入球的总数。
当枚举到 $j$,先令 $mp[c_j] \gets mp[c_j] + 1$,如果 $(mp[c_j] - 1) \bmod k + 1 = 1$ 意味着需要新开一个盒子来装这个球,更新 $sz \gets sz+1$。此时直接一次性把后面颜色也是 $c_j$ 的球装入这个盒子,即令 $\text{ret} \gets \text{ret} + \min\left\{ k, \, s_{c_j} - (mp[c_j] - 1) \right\}$,其中 $s_{c_j} - (mp[c_j] - 1)$ 表示包含第 $j$ 个球在内的剩余还没被装入的颜色为 $c_j$ 的球的数量。然后 $j$ 继续往右枚举,直到 $sz = m$ 或者 $j > i+n-1$。
当 $i$ 加 $1$ 后区间就变成了 $[i+1, i+n]$,变化的地方只有:原本的 $c_{i}$ 被删除,$c_{i+1}$ 变成了第一个元素;$c_{i+n}$ 被插入成为最后一个元素。意味着首先需要令 $mp[c_{i}] \gets mp[c_{i}] - 1$,一样的如果发现 $mp[c_{i}] \bmod k = 0$,说明删除这个球后盒子变空了,更新 $sz \gets sz-1$,同时令 $\text{ret} \gets \text{ret} - \min\left\{ k, \, s_{c_i} - mp[c_i] \right\}$,注意只要盒子不为空就会用后面同一种颜色的球装满。接着只要 $sz < m$,就按照上述的做法将 $j$ 往后移动。最后 $\text{ret}$ 就是区间 $[i+1, i+n]$ 中能装的球的数量。
之所以新开盒子就一次性把后面一样颜色的球装进来,是为了让避免 $j$ 每次都把整个区间遍历一遍,这样做能让指针 $j$ 具有单调性,即当 $i$ 往右移动时 $j$ 也只会往右移动。
AC 代码如下,时间复杂度为 $O(n)$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int c[N * 2];
int s[N];
int mp[N];
int main() {
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for (int i = 0; i < n; i++) {
scanf("%d", c + i);
c[i + n] = c[i];
s[c[i]]++;
}
int ret = 0, sz = 0;
for (int i = 0, j = 0; i < n; i++) {
if (i) {
mp[c[i - 1]]--;
if (mp[c[i - 1]] % k == 0) {
sz--;
ret -= min(k, s[c[i - 1]] - mp[c[i - 1]]);
}
}
while (j < i + n && sz < m) {
mp[c[j]]++;
if ((mp[c[j]] - 1) % k + 1 == 1) {
sz++;
ret += min(k, s[c[j]] - mp[c[j]] + 1);
}
j++;
}
printf("%d\n", ret);
}
return 0;
}
参考资料
Editorial - Toyota Programming Contest 2024#1(AtCoder Beginner Contest 337):https://atcoder.jp/contests/abc337/editorial
标签:box,Ball,Color,balls,Problems,frontmost,color,ball,mp From: https://www.cnblogs.com/onlyblues/p/17978169