首页 > 其他分享 >D2. Zero-One (Hard Version)

D2. Zero-One (Hard Version)

时间:2022-09-20 19:12:07浏览次数:50  
标签:cnt min read ll Hard pos Zero D2 getchar

题意

给定\(n,x,y\)和两个01串,字符串的长度为\(n\),现在你可以选择一个\(l\)和\(r\)(\(1\leq{l}<{r}\leq{n}\)),将\(a_l\)变成\(1-a_l\),将\(a_r\)变成\(1-a_r\),\(l+1=r\),则代价是\(x\),否则代价是\(y\),操作次数不限,求使两个串相同的最小代价,若无解输出-1

题解

设两个01串有\(cnt\)个位置不同,如果\(cnt\)为奇数,显然无解

如果\(cnt\)是偶数,以下进行分类讨论

  1. \(x\geq{y}\)

    特判一下\(cnt=2\)且这两个位置是相邻的情况,此时的答案为\(min(2*y,x)\)

    否则,我们总可以选\(cnt/2\)组不相邻的位置(因为选相邻总是不优的),此时答案为\(cnt/2*y\)

  2. \(x<y\)

​ 处理出所有两个01串不同的位置,原问题等价于把这些位置分成\(cnt/2\)组,每组的策略如下:

设这两个位置是\(l\)和\(r\),相邻的话显然直接操作,不相邻的话,直接操作或者移动某个位置,直到相邻后再操作

因此,最小代价为\(min(y,(r-l)*x)\)

​ 我们在pos数组上考虑区间dp,考虑区间\([l,r]\),我们可以证明dp只有三种情况:\(l,l+1\)同组,\(r,r-1\)同组,\(l,r\)同组

预处理区间长度为2的情况,只dp区间长度为偶数的区间,答案即为\(f[1][cnt]\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5007;
ll n,x,y,a[N],b[N],f[N][N],pos[N];
void read(ll &x){
    char c=getchar();
    x=0;
    while(!isdigit(c)){
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
}
ll read(){
    char c=getchar();
    while(c!='0'&&c!='1'){
        c=getchar();
    }
    return c-'0';
}
ll calc(ll l,ll r){
    return min((r-l)*x,y);
}
void work(){
    ll i,j,cnt=0;
    read(n),read(x),read(y);
    for(i=1;i<=n;++i){
        a[i]=read();
    }
    for(i=1;i<=n;++i){
        b[i]=read();
    }
    for(i=1;i<=n;++i){
        if(a[i]!=b[i]){
            pos[++cnt]=i;
        }
    }
    if(cnt%2){
        puts("-1");
        return;
    }
    if(x>=y){
        if(cnt==2&&pos[2]-pos[1]==1){
            printf("%lld\n",min(2*y,x));    
        }
        else{
            printf("%lld\n",cnt/2*y);
        }
    }
    else{
        for(i=1;i<cnt;++i){
            f[i][i+1]=calc(pos[i],pos[i+1]);
        }
        for(i=4;i<=cnt;i+=2){
            for(j=1;j+i-1<=cnt;++j){
                ll l=j,r=j+i-1;
                f[l][r]=min(min(f[l+2][r]+calc(pos[l],pos[l+1]),f[l][r-2]+calc(pos[r-1],pos[r])),
                f[l+1][r-1]+calc(pos[l],pos[r]));
            }
        }
        printf("%lld\n",f[1][cnt]);
    }
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        work();        
    }
    return 0;
}

标签:cnt,min,read,ll,Hard,pos,Zero,D2,getchar
From: https://www.cnblogs.com/DGJG/p/16712169.html

相关文章

  • Codeforces Round #821 D2
    D2.Zero-One(HardVersion)我们由D1可知当我们的y小于x/2时我们可以用2y来减小相邻的cost那我们考虑要是y比较大的时候我们也可以用多个x来减小cost我们可以轻松的......
  • Codeforces #821 Div2(A~D2)题解
    CF#821Div2AConsecutiveSum题目:​ 选择\(i\)和\(j\),如果\(j=i+xk(x=R)\),可以交换\(i,j\)。任意选择一段长度为k的相加。思路:​ 题目等价于在下标\(mod\)k相同......
  • 新开源HTML5单文件网页版ACME客户端,可在线申请Let's Encrypt、ZeroSSL免费HTTPS多域名
    目录开源项目的起源项目地址使用方法第一步:选择Let'sEncrypt、ZeroSSL或其他证书颁发机构第二步:证书配置,填写域名第三步:完成域名所有权的验证第四步:下载保存证书PEM文件源......
  • C# 四舍五入 MidpointRounding.AwayFromZero
    ROUND()是C#中math的一个成员函数.System.Math.Round(),这个函数有四种用法,最长用的是对小数点位数的舍入.但这和现实生活中的“四舍五入”有一定区别,也有别JAVA中Math.Round(......
  • git reset --hard 撤回后commit的代码消失了的解决办法
    楼主在今天的工作中使用了这个命令gitreset--hard撤回后commit的代码消失了,因为有commit,所以暂时得到了拯救,太不容易了,差点以为自己写的代码没了。网上到处找帖子,看看......
  • 题解【CF1702G2 Passable Paths (hard version)】
    题目传送门。考虑建立虚树然后再上面搞树形DP。于是这道题就变成分讨题。设\(f_i\)表示\(i\)子树内的答案。若\(f_i=1\),表示\(i\)子树内的特殊点可以被一条链覆......
  • word2vec
    Word2vec,是一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模......
  • ShardingSphere-JDBC
    概述ApacheShardingSphere‐JDBC可以通过Java,YAML,Spring命名空间和SpringBootStarter这4种方式进行配置,开发者可根据场景选择适合的配置方式。本文章主要讲解数......
  • Word2Vec
    词嵌入1.为什么使用词嵌入?one-hot向量(长度为词库大小,去重排序,一个one-hot仅在单词序号处取1,其余均为0)可以表示词,但是各个单词的one-hot乘积均为0,也就是看不出关......
  • CF1702G2 Passable Paths (hard version)
    PassablePaths(hardversion)给出一棵大小为\(n\)的树,\(q\)次询问,每次给出一大小为\(m\)的点集,判断是否存在一条链覆盖这些点,注意这条链可以经过其他点。\(n,\sum......