* Dytechlab Cup 2022 A. Ela Sorting Books

发布时间 2023-09-09 20:30:21作者: zsxuan

\(n\) 本书必须分成 \(k\) 部分在书架(\(k \mid n\)),每本书用一个小写的拉丁字母 \([a, y]\) 表示。每部分必须有严格 \(\frac{n}{k}\) 本书。

当所有书分配完成后,对于每个部分编号为 \(1, 2, \cdots, k\) ,每部分的有 \(\frac{n}{k}\) 本书,他们的 \(MEX\) 表示这个部分,作为代表字符。希望从 \(1\)\(k\) 部分的代表字符构成的字符串字典序最大。

输出这个代表字符。

贪心的结合:字典序思维结合 \(MEX\) 思维。

先按字典序思维考虑,从 \(1\)\(k\) 考虑。希望 越前面得到的字符 字典序越大。

假设当前位置为 \(i\) ,再按 \(MEX\) 思维考虑。希望当前的 \(MXE\) 尽可能大。即能够连续得到的字符尽可能多。

我们直接从贡献角度考虑。统计出 \(cnt_0 \sim cnt_{25}\)

遍历 \(1 \sim k\) 个部分。对于每个部分,存在 \(\frac{n}{k}\) 个字符,即连续字符串最后一个的取值可能为 \(0 \sim \frac{n}{k} - 1\) ,在这个区域枚举。

  • 用指针 \(j\)\(0 \sim \frac{n}{k} - 1\) 从小到大枚举字符,连续放入。\(cnt_j--\)
  • 当出现 \(cnt_j = 0\) ,即连续中断。可以确定此时 \(mex = j\) 。枚举可以结束。
    • 提前结束导致后一段空余的空间,在整体程序结束后可以随意填入,不影响结果。
  • 所有字符都可以连续出现,则 \(mex = \frac{n}{k}\) ,不妨初始化成它。
view
#include <bits/stdc++.h>
void solve() {
	int n, k; std::cin >> n >> k;
	int cnt[26] = {0};
	std::string str; std::cin >> str;
	for (int i = 0; i < n; i++) cnt[str[i] - 'a'] += 1;
	std::string ans = "";
	for (int i = 1; i <= k; i++) {
		int mex = n / k;
		for (int j = 0; j < n / k; j++) {
			if (cnt[j] > 0) cnt[j]--;
			else { mex = j; break; }
		}
		ans += (char)('a' + mex);
	}
	std::cout << ans << '\n';
}
signed main() {
	int _ = 1; std::cin >> _;
	while (_--) solve();
	return 0;
}