Loading

[AGC052E] 3 Letters 题解

妙妙题。

思路

我们考虑将一个字符串 \(s\) 看作一个序列 \(a\)

我们要求:

  1. \(s_i=\text{a},a_i\equiv 1 \pmod3\)
  2. \(s_i=\text{b},a_i\equiv 2 \pmod3\)
  3. \(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";
}
posted @ 2024-10-08 17:14  JiaY19  阅读(18)  评论(0)    收藏  举报