题解:【ARC132D】 Between Two Binary Strings

题目链接

首先我们记要寻找的“位于 \(s\)\(t\) 之间的字符串”为 \(c\) 串,\(s\) 串中的第 \(i\)\(1\) 位置为 \(cnts_i\)\(t\) 串中的第 \(i\)\(1\) 位置为 \(cntt_i\)\(c\) 串中的第 \(i\)\(1\) 位置为 \(cntc_i\),根据定义这个 \(c\) 串需要满足 \(\min(cnts_i,cntt_i) \le cntc_i \le \max(cnts_i,cntt_i)\)

容易想到我们要使答案尽可能大,就要尽可能多的让相同的数字凑在一起。考虑贪心,将 \(1\) 插入 \(0\) 中,由于 \(c\) 串所要满足的性质定下了每一个 \(1\) 可以放置的区间,所以我们应该将每一段的 \(1\) 尽可能向后放,然后检查后面的每一段能不能接着放 \(1\),如果可以放则放,不可以则重新另起一段,再从这一段的最后面开始放 \(1\)

满心欢喜的交上去,你会发现红了一片,这是为什么捏?

考虑这么一组数据:

1 1 1 1 0 0
0 1 1 1 1 0

我们如果按照上面的贪心策略,会得到答案 0 1 1 1 1 0,但显然 1 1 1 1 0 0 更优。这是因为如果我们在第一位上可以放 \(1\),并且有一个串的前面有一部分 \(0\),第一段 \(1\) 的后面又有一部分 \(0\) 时,我们把 \(1\) 往后放的策略就会使两段 \(0\) 分开,这时就应该把第一段 \(1\) 放在最前头,使得保证在同等贡献数量的 \(1\) 的情况下,\(0\) 的贡献也尽可能大。也非常好处理,让第一个 \(1\) 在最开头就好了,剩下的还上面的贪心一致。

实现大概就是单指针,只需要枚举放 \(1\) 的位置,遍历一遍存储答案的数组统计即可,时间复杂度 \(O(n)\)

\(Code\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

namespace LgxTpre
{
    static const int MAX=500010;
    static const int INF=20070707070707;

    int n,m,len;
    char a[MAX],b[MAX];
    int posa[MAX],cnta;
    int posb[MAX],cntb;
    int L[MAX],R[MAX];
    int num[MAX],ans;

    inline int getans(int begin)
    {
        int sum=0;
        memset(num,0,sizeof num);
        num[begin]=1;
        for(int i=2,last=begin;i<=m;++i)
            if(last+1>=L[i]&&last+1<=R[i])
                ++last,num[last]=1;
            else    
                last=R[i],num[last]=1;
        for(int i=1;i<len;++i)
            if(num[i]==num[i+1])
                ++sum;
        return sum;
    }

    inline void lmy_forever()
    {
        scanf("%lld%lld",&n,&m); len=n+m;
        scanf("%s",a+1); scanf("%s",b+1);
        for(int i=1;i<=len;++i) if(a[i]=='1') posa[++cnta]=i;
        for(int i=1;i<=len;++i) if(b[i]=='1') posb[++cntb]=i;
        for(int i=1;i<=m;++i)
            L[i]=min(posa[i],posb[i]),
            R[i]=max(posa[i],posb[i]);
        ans=max(ans,getans(R[1]));
        if(L[1]==1) ans=max(ans,getans(L[1]));
        cout<<ans;
        return;
    }
}


signed main()
{
    LgxTpre::lmy_forever();
    return (0-0);
}
posted @ 2022-11-23 20:23  LgxTpre  阅读(53)  评论(0编辑  收藏  举报