解题思路
题面已经把策略写死,本质是按规则模拟,而不是另寻最优划分。
- 先算每波容量。记 q=⌊p/b⌋,r=pmodb,则前 b−r 波容量为 q,最后 r 波容量为 q+1。余数一定摊在末尾,不能摊到前几波。
- 从第 1 波填到第 b 波。每个波次单独维护 d 个集合:该维在本波次里已经出现过的标签。换波次时集合清空。
- 波次内每要再拿一台,就扫所有未入选主机,算增量:该机第 j 维标签若不在本波次第 j 个集合里,就加 1。增量最大者入选;增量相同取 nid 更小的。入选后把它的各维标签写入本波次集合,并标记已用。
- 一个波次刚开始时集合是空的,所有剩余主机增量都等于 d,因此每波第一个一定是当前剩余 nid 最小的那台。后面几台才会因增量拉开差距。
- 该波次名单收集齐后按 nid 升序输出。常见假解:余数加到前几波、增量相对「全局已选」而不是「本波次」、维度混成一个集合、增量打平时取大编号、输出不排序。
题目背景
云上要给一大批计算节点做版本滚动。为了把风险压住,升级会拆成若干波次,也就是常说的灰度放量。
越靠前的波次越希望把各类机型都点到,好尽早把隐患暴露出来。
任务描述
手里有 p 台主机,每台带着 d 个维度的标签(比如板型、系统发行版)。某一维上标签相同,就认定这两台在该维属于同一类。
请按下面的规则排出分波方案:越靠前的波次,标签种类要尽量铺得开。
核心规则
-
波次容量:
主机总数记为 p,波次总数记为 b。
- 基准容量 q=⌊p/b⌋。
- 余数 r=pmodb。
- 前 b−r 个波次容量都是 q,最后 r 个波次容量都是 q+1。
-
增量尽量大:
填当前波次时,只能从未入选的主机里挑。看哪一台还能给本波次补进最多尚未出现的标签。
- 增量:该机某个维度上的标签,若本波次已入选的机器里还没出现过,就记一分。
- 先比增量,越大越先拿。
- 增量打平则拿 nid 更小的那台。
-
执行顺序:
从第 1 波填到第 b 波,每波填满为止。某台一旦进了某一波,后面的波次不再考虑它。
输入描述
-
首行两个整数 p 和 d,即主机台数与标签维度。(1≤p≤2×102, 1≤d≤2)
-
随后 p 行:每台主机一行,格式为
nid tag_1 tag_2 ... tag_d
-
末行一个整数 b,即波次总数。(1≤b≤2×101)
输出描述
输出 b 行。第 i 行给出该波次里的 nid,同一行按数值升序,相邻编号用空格隔开。
样例1
输入
4 1
10 A
11 A
12 A
13 A
2
输出
10 11
12 13
说明
- 4÷2=2 余 0,两波容量都是 2。
- 标签全是 A,第一台进波次后其余增量都变成 0。
- 增量打平时按 nid 从小到大,故第一波 10 11,其余进第二波。
样例2
输入
6 2
1 X P
2 X Q
3 Y P
4 Y Q
5 Z Q
6 Z R
2
输出
1 4 6
2 3 5
说明
- 6÷2=3 余 0,两波容量都是 3。
- 第一波:空盘先拿 nid=1(增量 2);已有 {X,P} 后再拿 nid=4(增量 2);已有 {X,Y,P,Q} 后再拿 nid=6(增量 2)。
- 剩下 2,3,5 进第二波。
提示
- 多样性按各维标签种类相加;越靠前的波次越优先把种类铺开。
- 容量:总数 p、波次 b,基准是 ⌊p/b⌋,多出来的台数摊到最后若干波。