[AGC052E] 3 Letters 题解
妙妙题。
思路
我们考虑将一个字符串 \(s\) 看作一个序列 \(a\)。
我们要求:
- 当 \(s_i=\text{a},a_i\equiv 1 \pmod3\)
- 当 \(s_i=\text{b},a_i\equiv 2 \pmod3\)
- 当 \(s_i=\text{c},a_i\equiv 0 \pmod3\)
那么发现,由于 \(s\) 中相邻字符都不相同,也就意味着 \(|a_i-a_{i-1}|=1\)。
那么当我们 \(s\) 与 \(a_1\) 确定后,整个 \(a\) 序列就确定了。
考虑修改。
我们在修改一个字符的时候,要求两侧的字符相同,并都与中间的不同。
在序列上的表示即为:
\[x,x+1/x-1,x
\]
那么我们只能把 \(x+1\) 和 \(x-1\) 互相变化。
因此我们的操作就是每一次给一个数加减二。
然后我们考虑在这种操作下,我们怎样把两个数值的序列 \(a,b\) 变得相同。
首先,对于每一个位置,两个数的奇偶性要一样,否则就无解。
有一个比较简单的下界是:\(\sum_{i=1}^n\frac{|b_i-a_i|}{2}\)。
我们可以证明能够达到这个下界,具体的我们一定可以找到一个位置将其距离缩小二。
然后我们就把字符串距离转化为了序列的距离了。
我们考虑对两个字符串都固定一个序列。
由于两个都固定没有意义,我们可以将一个随意处理。
比如我们知道了 \(s\) 的 \(a\) 序列。
现在需要构造 \(t\) 的 \(b\) 序列。
由于 \(b_1,a_1\) 的奇偶性相同,也要和第一个字符模三一样。
那么可以令:
\[b_1=x+6\times k
\]
相当于我们求出任意一个 \(b\) 后可以将它全部偏移 \(6\times k\)。
考虑此时的贡献:
\[\begin{align}
&=\sum_{i=1}^n \frac{|(a_i-b_i)+6\times k|}{2}\\
&=\sum_{i=1}^n \frac{|(b_i-a_i)-6\times k|}{2}
\end{align}
\]
那么只要求 \(b_i-a_i\) 的中位数,求能取到最优的答案。
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a[500010];
int b[500010];
string s;
string t;
inline int calc(int x) {
int res = 0;
for (int i = 1; i <= n; i++)
res += abs(a[i] - x) / 2;
return res;
}
signed main() {
cin >> n >> s >> t;
if (s[0] == 'A') a[1] = 1;
if (s[0] == 'B') a[1] = 2;
if (s[0] == 'C') a[1] = 3;
for (int i = 2; i <= n; i++) {
if (s[i - 2] == 'A') a[i] = a[i - 1] + (s[i - 1] == 'B' ? 1 : -1);
if (s[i - 2] == 'B') a[i] = a[i - 1] + (s[i - 1] == 'C' ? 1 : -1);
if (s[i - 2] == 'C') a[i] = a[i - 1] + (s[i - 1] == 'A' ? 1 : -1);
}
if (t[0] == 'A') b[1] = 1;
if (t[0] == 'B') b[1] = 2;
if (t[0] == 'C') b[1] = 3;
for (int i = 2; i <= n; i++) {
if (t[i - 2] == 'A') b[i] = b[i - 1] + (t[i - 1] == 'B' ? 1 : -1);
if (t[i - 2] == 'B') b[i] = b[i - 1] + (t[i - 1] == 'C' ? 1 : -1);
if (t[i - 2] == 'C') b[i] = b[i - 1] + (t[i - 1] == 'A' ? 1 : -1);
}
if (a[1] % 2 != b[1] % 2) {
for (int i = 1; i <= n; i++) b[i] += 3;
}
for (int i = 1; i <= n; i++) a[i] -= b[i];
sort(a + 1, a + n + 1);
int w = a[n / 2 + 1] / 6 * 6;
int s = 1e18;
for (int i = -5; i <= 5; i++)
s = min(s, calc(w + i * 6));
cout << s << "\n";
}

浙公网安备 33010602011771号