寒假第一天:贪心2

2. D - Between Two Binary Strings (atcoder.jp)

        D - between two binary strings

        主要思考那个距离怎么解决,即怎么找出满足题意的介于s与t距离之间的串。

        题目的每个条件都不是没有用的,有时还需观察样例。

对于两个串s,t属于集合(p,q)它们的0,1个数是相同的,考虑每个1所在位置。设s串中第i个1的位置是d1[i],t串中第i个1的位置是d2[i],对于s和t串,它们两个之间的距离就是\sum |d1[i]-d2[i]| ,满足题意的同类型的串设为k,它每个1的位置设为d3[i],满足min(d1[i],d2[i]) <= d3[i] <= max(d1[i],d2[i])

接下来我们开始思考:要求最大的价值,我们应该怎样决策?我们肯定希望相同的元素能够凑在一起最好。也就是对于可供我们选择的串,我们希望相邻的1或0能够凑在一起。对k串的第i个1的,假设前面的1都已经选好位置,我们能选择的1的位置实际是在一个区间内的。

        由于希望相同的凑在一起,我们思考1可不可以放在最前面。

        如果此时1的最靠前的位置能够与前一个1靠在一起,能够证明此时放在最前面是最优的。证明:设当前1能放的区间是 l 到 r (闭区间),若将1放在 l+1 到 r 的区间内,当把1放到 l 的位置上时,可以发现 总价值会增加2(1与1贴贴,0与0贴贴),可知放在 l 的位置上最优。

        如果此时的1的最靠前的位置不能与前一个1靠在一起,能够证明此时放在最后一定是最优的。设当前1能放的区间是 l 到 r (闭区间),若将1放在 l 到 r-1 的区间内,当把1放到 r 的位置上时,若后面的1能够与当前的1靠在一起,此时肯定最优;若后面的1不能与当前的1靠在一起,此时无论我们手中的1放在哪里,都一样。

        虽然主体过程已经思考完毕,但是还有细节需要注意:由于我们的归纳假设是建立在前面1已经放好的前提下,因此在考虑放置最前面一个1时,不能按照我们前面的放法。此时只需枚举放在最前面和最后面即可:因为当不在最前面和最后面时,我们移动1得到的结果都一样。

        代码:

        

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int n,m,d1[N],d2[N];
string s,t;

int solve(int st){
    //cout << n << "!" << endl;
    int ans=0,last=st;
    ans+=max(st-1,0);
    for(int i=2;i<=n;i++){
        //cout << last << endl;
        int maxpos=max(d1[i],d2[i]),minpos=min(d1[i],d2[i]);
        if(minpos<=last+1){
            ans++;
            last++;
        }
        else{
            ans+=max(maxpos-last-2,0);
            last=maxpos;
        }
        //cout << ans << "!" << endl;
    }
    ans+=max(n+m-1-last-1,0);
    // cout << ":" << last;
    // cout << ans << "!" << endl;
    return ans;
}

int main(){
    cin >> m >> n;
    cin >> s >> t;
    int h1=0,h2=0;
    for(int i=0;i<s.size();i++){
        if(s[i]=='1')   d1[++h1]=i;
        if(t[i]=='1')   d2[++h2]=i;
    }
    int ans=solve(d1[1]);
    ans=max(ans,solve(d2[1]));
    cout << ans;
    return 0;
}

但是WA了一个点😥

我不会,长大后再学习~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值