zoukankan      html  css  js  c++  java
  • ARC132DBetween Two Binary Strings【贪心】

    正题

    题目链接:https://atcoder.jp/contests/arc132/tasks/arc132_d


    题目大意

    给出两个恰好有\(n\)\(1\)\(m\)\(0\)的字符串\(s,t\),定义两个字符串距离为通过交换两个相邻的字符把一个变成另一个的最小步数。

    对于字符串\(k\)如果\(dis(s,k)+dis(k,t)=dis(s,t)\)那么\(k\)\(s,t\)之间。

    定义一个字符串的权值为相邻的相同字符对数。

    求所有在\(s,t\)之间的字符串中权值最大是多少。

    \(1\leq n+m\leq 3\times 10^5\)


    解题思路

    先考虑在\(s,t\)之间的字符串有什么性质,显然的我们对于求\(dis(s,t)\)的时候最优的策略肯定是把\(s\)的第\(i\)\(1\)移动到\(t\)的第\(i\)\(1\)处。

    也就是对于两个串中第\(i\)\(1\)的位置记为\(x,y\),那么就是一个一要从\(x\rightarrow y\),也就是在\(s\sim t\)之间的字符串第\(i\)个一肯定在\(x\sim y\)这个范围。

    这样我们处理出每个\(1\)的合法区间\(l_i,r_i\),显然的\(l_i\)\(r_i\)必定递增,因为交换两个\(1\)的顺序必定不划算。所以可以考虑贪心。

    不考虑边界的问题,那么我们显然要让\(1\)的连续段尽量少,那么从小到大考虑\(l,r\)如果能和上一个放一起就放一起,不然就放在\(r\)的位置最赚。

    然后考虑边界,右边界可以直接判断因为我们肯定是尽量往右放的。左边界的话我们如果\(l_1=1\)我们就分两种情况考虑,也就是第一个放在左边界和第一个放在\(r_1\)两种情况取个最大值。

    时间复杂度:\(O(n+m)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define lowbit(x) (x&-x)
    using namespace std;
    const int N=6e5+10;
    int A,B,m,n,t[N],l[N],r[N],ans,prt;
    char a[N],b[N];
    //void Change(int x,int val){
    //	while(x<=m){
    //		t[x]+=val;
    //		x+=lowbit(x);
    //	}
    //	return;
    //}
    //int Ask(int x){
    //	int ans=0;
    //	while(x){
    //		ans+=t[x];
    //		x-=lowbit(x);
    //	}
    //	return ans;
    //}
    int main()
    {
    	scanf("%d%d",&A,&B);m=A+B;
    	scanf("%s",a+1);
    	scanf("%s",b+1);
    	for(int i=1;i<=m;i++)
    		if(a[i]=='1')l[++n]=i;
    	n=0;
    	for(int i=1;i<=m;i++)
    		if(b[i]=='1')r[++n]=i;
    	for(int i=1;i<=n;i++){
    		if(l[i]>r[i])swap(l[i],r[i]);
    	}
    	int last=-1;
    	for(int i=1;i<=n;i++){
    		if(l[i]<=last+1)last++;
    		else ans++,last=r[i];
    	}
    	ans=ans*2;
    	if(last!=m)ans++;
    	prt=m-ans;
    	if(l[1]==1){
    		last=1;ans=1;
    		for(int i=2;i<=n;i++){
    			if(l[i]<=last+1)last++;
    			else ans+=2,last=r[i];
    		}
    		if(last!=m)ans++;
    		ans=m-ans;
    		prt=max(prt,ans);
    	}
    	printf("%d\n",prt);
    	return 0;
    }
    
  • 相关阅读:
    docker实例之mysql的使用
    使用Dockerfile创建ssh服务的镜像02
    添加ssh服务构建新镜像-docker commit 方式01
    Keepalived
    ubuntu网卡配置
    升级openssl
    源码安装nginx env
    dockerfile
    shell字符截取
    MYSQL导入/迁移后事件不执行
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15735415.html
Copyright © 2011-2022 走看看