[NOIP2024] 编辑字符串

比较简单的贪心

首先按照t1,t2中连续的1将其分成若干段。以样例为例,t1=111010,那么第一段是s1[13],第二段是s1[5]t2=101101,那么第三段是s2[1],第四段是s2[34],第五段是s2[6].同时统计每一段中,s1(s2)10的数量

然后可以知道,如果对一个位置i,有t1[i]=t2[i]=0,那么答案是可以直接统计的(若s1[i]=s2[i]则答案加一,否则答案不变);若t1[i]+t2[i]=1则我们尽量匹配(比如t1=1,t2=0,s2[i]=0,那么考虑i所在的段剩下的0的个数,如果还有剩下的0,那么将这个0s2[i]进行匹配,并将i所属的这个段的0的个数减一);在优先考虑完所有的t1[i]+t2[i]=1的位置后,再考虑t1[i]+t2[i]=2的位置i,随意将剩下的0/1进行匹配即可

上述做法的正确性可以用决策包容性证明。简单来说,就是任意一个位置对答案的贡献只有1,上面的做法,我们在分配任意一个0/1的时候,都保证了这个0/1对答案的贡献增加了一。如果我们不把这个0/1分配到这个位置,分配到其他位置的贡献也是一,等价于就放在这个位置

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
int n;
char s1[N],s2[N],t1[N],t2[N];
int mark[N],belong[2][N],sum[N][2],cnt;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		cnt=0;//cnt记录段的数量 
		for(int i=1;i<=n;i++) 
		{
			for(int j=0;j<=1;j++) belong[j][i]=sum[i][j]=0;
			//belong[0/1][i]表示s1/s2的位置i所属的段的标号
			//sum[i][0/1]表示编号为i的段的0/1的个数 
			mark[i]=0;//mark[i]表示位置i的类别 
		}
		scanf("%s%s",s1,s2);
		scanf("%s%s",t1,t2);
		for(int i=1;i<=n;i++)
		if(t1[i-1]=='1') mark[i]++;
		for(int i=1;i<=n;i++)
		if(t2[i-1]=='1') mark[i]+=2;
		for(int i=1;i<=n;i++)
		if(t1[i-1]=='1')
		{
			cnt++;
			int j=i;
			while(j<=n&&t1[j-1]=='1')
			{
				belong[0][j]=cnt;
				sum[cnt][s1[j-1]-'0']++;
				j++;
			}
			i=j-1;
		}
		for(int i=1;i<=n;i++)
		if(t2[i-1]=='1')
		{
			cnt++;
			int j=i;
			while(j<=n&&t2[j-1]=='1')
			{
				belong[1][j]=cnt;
				sum[cnt][s2[j-1]-'0']++;
				j++;
			}
			i=j-1;
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		if(!mark[i]&&s1[i-1]==s2[i-1]) ans++;
		for(int i=1;i<=n;i++)
		if(mark[i]==1&&sum[belong[0][i]][s2[i-1]-'0'])
		{
			sum[belong[0][i]][s2[i-1]-'0']--;
			ans++;
		}
		else if(mark[i]==2&&sum[belong[1][i]][s1[i-1]-'0'])
		{
			sum[belong[1][i]][s1[i-1]-'0']--;
			ans++;
		}
		for(int i=1;i<=n;i++)
		if(mark[i]==3) 
		{
		    if(sum[belong[0][i]][0]&&sum[belong[1][i]][0])
		    {
		        ans++;
		        sum[belong[0][i]][0]--,sum[belong[1][i]][0]--;
		    }
		    if(sum[belong[0][i]][1]&&sum[belong[1][i]][1])
		    {
		        ans++;
		        sum[belong[0][i]][1]--,sum[belong[1][i]][1]--;
		    }
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @   最爱丁珰  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2024-01-18 陨石的秘密
2024-01-18 减操作
2024-01-18 低买
2024-01-18 移动服务
2024-01-18 分级
2024-01-18 滑雪
2024-01-18 开垦农田
点击右上角即可分享
微信分享提示