CF 1370 E - Binary Subsequence Rotation 思维

首先s[i]==t[i]的都可以不用管。(因为我们每次选的是子序列,完全可以跳过这些)

我们把s[i]!=t[i]的部分提取出来,让s[i]==1的设为1,否则设为0.

得到一个01串。

比如:

0111000001
1000001110

转化为:01110001   (目标是让所有01互换位置)

每次可选取一个子序列,然后让所有数往右移动(最右边到最左边)

我们发现:

一次操作可以让所有101010这样的01交替串,的01互换位置,然后就可以不管他们(因为此时s[i]==t[i])

一次操作也可以让所有010101这样的01交替串,的01互换位置,然后就可以不管他们(因为此时s[i]==t[i])

所以问题转化为了:寻找01交题串的个数。

比如01110001  :

1258是一个01交替串:0101

36是一个01交替串:10

剩下47是一个01交替串:10

需要操作三次。

找01交替串就很简单了,直接类比括号序列查找即可。

 

 

官方题解给的是:

查找1-n的最大字段和,就是结果。(不过这里把0改成了-1)

比如刚才的样例转化为:-1 1 1 1 -1 -1 -1 1

最大子段和为3.

这种思路可以查找任意l-r之间的操作数。

正确性证明:

最大子段和其实就是01交题串的个数。

最大子段和中:-1   1 成对先去掉不管,剩余的1中任意两个1都不可能再一次序列中同时变为0.

 因为此时任意两个1中间都没有-1  去凑成01交替串。

由此证明最大字段和是 答案的下界(即答案大于等于最大字段和)

再考虑:

剩余的每个1都能与非最大子段和中的-1配对,(再连带上最大字段和中的  1,-1对)在一次操作中完成。

所以操作不会多于最大子段和中空闲1的数量。

即证明了最大字段和是答案的上界。

由此得证。

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e6+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
char s[M],t[M];
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
  	int n;
  	cin>>n;
  	cin>>(s+1)>>(t+1);
  	int a=0,b=0,na=0,nb=0;
  	for(int i=1;i<=n;i++)
  	{
  		if(s[i]=='1')na++;
  		if(t[i]=='1')nb++;
	}
	if(na!=nb)
	{
		cout<<-1<<endl;
		return 0;
	}
	int ans=0;
	//a: 前面以0结尾串的个数,b:前面以1结尾串的个数 
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='1'&&t[i]=='0')
		{
			if(a)a--,b++;//把当前1加到前面  以0结尾的串后面
			else b++,ans++;//前面无0结尾的串了,再开一个新串 
		}
		if(s[i]=='0'&&t[i]=='1')
		{
			if(b)b--,a++;
			else a++,ans++;
		}
	}  
	cout<<ans<<endl;
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值