1 条题解

  • 0
    @ 2026-5-5 18:59:25

    首先有一个结论:若 sisjs_i\not=s_j,交换 sis_isjs_j 且不改变它们中间的字符的代价为 ijk\lceil\frac{i-j}{k}\rceil

    首先,答案的下界显然为 ijk\lceil\frac{i-j}{k}\rceil,因为即使不管中间字符的顺序,也要进行这么多次操作。现在只需要证明一定能在 ijk\lceil\frac{i-j}{k}\rceil 次操作内完成即可。

    对于 ijki-j\le k 的情况,显然成立;现在考虑 ji>kj-i>k 的情况。若 sj=sj+ks_j=s_{j+k},我们可以先交换 sjs_jsj+ks_{j+k},再递归地考虑交换 sj+ks_{j+k}sis_i 即可;否则一定有 sj+ksis_{j+k}\not=s_i,先递归地考虑交换 sj+ks_{j+k}sis_i,再交换 sjs_jsj+ks_{j+k} 即可。

    由于每次操作都会将 iji-j 减少 kk,总操作次数即为 ijk\lceil\frac{i-j}{k}\rceil

    假如没有上取整,这显然是好做的:对于每一个 sitis_i\not=t_iii,若存在一个还没有被匹配过的 jj 满足 sjtjs_j\not=t_jsisjs_i\not=s_j,任选一个 jj 进行匹配即可,容易证明任何选择的答案都是相同且最优的;否则继续往后找,等待后面的数将其匹配。

    现在有了上取整,可以发现,如果 (ij)modk(i-j)\bmod k 不为 00,其值越小,损失越大,因为同样次数的交换还可以在多走 k((ij)modk)k-((i-j)\bmod k) 格。既然这样,在上面的过程中,我们不如选 (ij)modk(i-j)\bmod k 较大的 jj,从而减少损失的值。

    实现的时候,记录两个 set<pair<int, int>>,分别代表 si=0s_i=011 时符合条件的还没有被匹配的 jjjmodkj\bmod k 和下标。使 (ij)modk(i-j)\bmod k00 或尽量大的 jj 即为第一个 jmodkj\bmod k 大于等于 imodki\bmod kjj。若找不到,则为 jmodkj\bmod k 最小的一个 jj

    AC 代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    int n, k;
    string s, t;
    set<pair<int, int>> st[2];
    long long ans;
    int main() {
    	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    	cin >> n >> k >> s >> t;
    	for (int i = 0; i < n; i++) {
    		if (s[i] == t[i]) continue;
    		int vl = s[i] - '0';
    		if (st[vl].empty()) { st[!vl].insert({i % k, i}); continue; }
    		auto it = st[vl].lower_bound({i % k, 0});
    		if (it == st[vl].end()) it = st[vl].begin();
    		ans += ceil(1.0 * (i - (it -> second)) / k);
    		st[vl].erase(it);
    	}
    	cout << ans;
    	return 0;
    }
    
    • 1

    信息

    ID
    7601
    时间
    2000ms
    内存
    256MiB
    难度
    7
    标签
    递交数
    19
    已通过
    8
    上传者