AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 5583. 奶牛编舞    原题链接    困难

作者: 作者的头像   Jerrywang ,  2024-06-10 23:16:41 ,  所有人可见 ,  阅读 14


0


简要题意:给定两个 01 字符串 $a,b$,每次可以选择下标 $i,j$,其中 $|i-j|\le k$,交换 $a[i],a[j]$,求从 $a$ 变成 $b$ 的最小步数。

如果 $a[i]=b[i]$,直接跳过。否则有两种情况:$a[i]=0, b[i]=1$ 或 $a[i]=1, b[i]=0$。

如果有 $i,j$ 满足 $a[i]=0, b[i]=1, a[j]=1, b[j]=0$,则交换 $i,j$。这样的 $i,j$ 分别放在二分图的两边,构造出了二分图模型。考虑如何加速二分图匹配。

交换下标 $i,j(i<j)$ 的代价是 $\lceil \frac{j-i}{k} \rceil$,不考虑向上取整,那么最小的 $i$ 匹配最小的 $j$,次小的 $i$ 匹配次小的 $j$,以此类推,一定是最优策略。

再考虑有向上取整怎么办。一个显然的贪心策略是,使“浪费”尽量少,也就是说 $j\equiv i$ 是最优的,$j\equiv i+1$ 次优,等等。

考虑使用两个 set 维护二分图的两边,使用二分查找寻找最不“浪费”的匹配点。

// Title:  Cowreography
// Source: USACO24OPEN Gold
// Author: Jerrywang
#include <bits/stdc++.h>
#define ll long long
#define rep(i, s, t) for(int i=s; i<=t; ++i)
#define debug(x) cerr<<#x<<":"<<x<<endl;
const int N=1000010;
using namespace std;

int n, k, a[N], b[N]; ll res;
set<pair<int, int>> S[2];
int main()
{
#ifdef Jerrywang
    freopen("E:/OI/in.txt", "r", stdin);
#endif
    scanf("%d%d", &n, &k);
    rep(i, 1, n) scanf("%1d", a+i);
    rep(i, 1, n) scanf("%1d", b+i);
    rep(i, 1, n) if(a[i]!=b[i])
    {
        auto &S1=S[a[i]], &S2=S[b[i]];
        if(S1.empty())
        {
            S2.insert({i%k, i}); continue;
        }
        auto it=S1.lower_bound({i%k, 0});
        if(it==S1.end()) it=S1.begin();
        int j=it->second;
        res+=(i-j+k-1)/k; S1.erase(it);
    }
    printf("%lld", res);

    return 0;
}

1 评论


用户头像
llll666666666   2024-07-28 18:15         踩      回复

sz


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息