F - Usual Color Ball Problems

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

posted @ 2024-01-21 19:00  onlyblues  阅读(49)  评论(0编辑  收藏  举报
Web Analytics