题解 P6709 【[CCC2020 T4] Swapping Seats】
本题解在博客页面显示正常。
原题链接:https://dmoj.ca/problem/ccc20s4
CCC 2020 题组:https://cemc.math.uwaterloo.ca/contests/computing/2020/ccc/seniorEF.pdf
本题解默认排序为从小到大排。
题意:给定一个
首先,考虑一下交换次数问题。
可以看看 USACO Training 的 Sorting a Three-Valued Sequence 这题,洛谷 P1459。
记:不在 排序之后 1 3 2 1 中
记:在排序之后 1 3 1 2 中
它启示我们:
值域仅为
推广到值域为
又因为这是个环,所以枚举 A)的起始位置,同时破环成链用前缀和维护前 A, B, C 即可。注意还要讨论一下 A 后面跟的是 B 还是 C,因为本题 A, B, C 的排列顺序不定。时间复杂度
这里还有一个小技巧,同时可以拓展一下思维。我们可以稍微化简一下式子。(这里 B 和 C 是对称的,只写一个)
可以稍微简化一点代码。
Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2000002;
int n, sa[maxn], sb[maxn], sc[maxn], suma, sumb, sumc, ans = INT_MAX;
char a[maxn];
int mo(int x) { return x % (n + 1) + 1; }
signed main() {
scanf("%s", a + 1); n = strlen(a + 1);
for (int i = n + 1; i <= (n << 1); ++i)
a[i] = a[i - n];
for (int i = 1; i <= n; ++i)
if (a[i] == 'A') ++suma;
else if (a[i] == 'B') ++sumb;
else ++sumc;
for (int i = 1; i <= (n << 1); ++i) {
sa[i] = sa[i - 1] + (bool)(a[i] == 'A');
sb[i] = sb[i - 1] + (bool)(a[i] == 'B');
sc[i] = sc[i - 1] + (bool)(a[i] == 'C');
}
for (int i = 1; i <= n; ++i) { // positions for A begins
int nx1 = i + suma, nx2;
// B is next
nx2 = nx1 + sumb;
ans = min(ans, max(sb[nx1 - 1] - sb[i - 1], sa[nx2 - 1] - sa[nx1 - 1]) + sumc - sc[i + n - 1] + sc[nx2 - 1]);
// C is next
nx2 = nx1 + sumc;
ans = min(ans, max(sc[nx1 - 1] - sc[i - 1], sa[nx2 - 1] - sa[nx1 - 1]) + sumb - sb[i + n - 1] + sb[nx2 - 1]);
}
return cout << ans << endl, 0;
}
参考 DMOJ 官方题解:https://dmoj.ca/problem/ccc20s4/editorial