社区讨论

求思路证明或证伪

P11361[NOIP2024] 编辑字符串参与者 3已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@m4cjn6b0
此快照首次捕获于
2024/12/06 17:28
去年
此快照最后确认于
2025/11/04 13:17
4 个月前
查看原帖
我的思路是以0为分界分别处理出每个连续1区间内的1和0的个数然后进行贪心,考场最后一个样例没过,官方数据65pts
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n;
char s1[N],s2[N],t1[N],t2[N];
struct node{
	int x,y,s1,s0;
}f1[N],f2[N];
int ans;
void init(char s[],char t[],node f[],int &num){//统计
	int lst=1;
	for(int i=1;i<=n;i++){
		if(t[i]=='0'){
			f[num].x=f[num].y=i;
			lst=i+1;
			if(s[i]=='0')
				f[num].s0++;
			else
				f[num].s1++;
			num++;
			continue;
		}
		if(s[i]=='0')
			f[num].s0++;
		else
			f[num].s1++;
		if(i==n){
			f[num].x=lst;
			f[num].y=i;
			break;
		}
		if(t[i+1]=='0'){
			f[num].x=lst;
			f[num].y=i;
			num++;
		}
	}
}
int main(){
//	freopen("edit.in","r",stdin);
//	freopen("edit.out","w",stdout);
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		memset(s1,0,sizeof(s1));
		memset(s2,0,sizeof(s2));
		memset(t2,0,sizeof(t1));
		memset(t2,0,sizeof(t2));
		cin>>s1+1>>s2+1>>t1+1>>t2+1;
		memset(f1,0,sizeof(f1));
		memset(f2,0,sizeof(f2));
		int num1=1,num2=1;
		ans=0;
		init(s1,t1,f1,num1);
		init(s2,t2,f2,num2);
//		for(int i=1;i<=num1;i++)
//			printf("%d %d %d %d\n",f1[i].x,f1[i].y,f1[i].s0,f1[i].s1);
//		puts("");
//		for(int i=1;i<=num2;i++)
//			printf("%d %d %d %d\n",f2[i].x,f2[i].y,f2[i].s0,f2[i].s1);
		int i=1,j=1;
    //神秘的贪心
		while(i<=num1||j<=num2){
//			printf("%d %d %d\n",i,j,ans);
			if(f1[i].y<f2[j].y){
				int minn=1e9;
				if(f1[i].x<f2[j].x)
					minn=f2[j].y-f1[i].x+1;
				int min0=min(f1[i].s0,f2[j].s0),min1=min(f1[i].s1,f2[j].s1);
				int sum=min(min0+min1,minn);
//				cout<<i<<" "<<j<<" "<<minn<<" "<<min0<<" "<<min1<<" "<<sum<<endl;
				ans+=min(min0+min1,minn);
				if(minn<min0+min1){
					if(min1>min0){
						f1[i].s1-=min(min1,minn);
						f2[j].s1-=min(min1,minn);
						f1[i].s0-=minn-min(min1,minn);
						f2[j].s0-=minn-min(min1,minn);
						i++;
						continue;
					}
					if(min0>=min1){
						f1[i].s0-=min(min0,minn);
						f2[j].s0-=min(min0,minn);
						f1[i].s1-=minn-min(min0,minn);
						f2[j].s1-=minn-min(min0,minn);
					}
					i++;
					continue;
				}
				f1[i].s0-=min0;
				f1[i].s1-=min1;
				f2[j].s0-=min0;
				f2[j].s1-=min1;
				i++;
			}else if(f1[i].y>f2[j].y){
				int minn=1e9;
				if(f2[j].x<f1[i].x)
					minn=f2[j].y-f1[i].x+1;
				int min0=min(f1[i].s0,f2[j].s0),min1=min(f1[i].s1,f2[j].s1);
				int sum=min(min0+min1,minn);
//				cout<<i<<" "<<j<<" "<<minn<<" "<<min0<<" "<<min1<<" "<<sum<<endl;
				ans+=min(min0+min1,minn);
				if(minn<min0+min1){
//					cout<<1<<endl;
					if(min1>min0){
						f1[i].s1-=min(min1,minn);
						f2[j].s1-=min(min1,minn);
						f1[i].s0-=minn-min(min1,minn);
						f2[j].s0-=minn-min(min1,minn);
						j++;
						continue;
					}
					if(min0>=min1){
						f1[i].s0-=min(min0,minn);
						f2[j].s0-=min(min0,minn);
						f1[i].s1-=minn-min(min0,minn);
						f2[j].s1-=minn-min(min0,minn);
					}
					j++;
					continue;
				}
				f1[i].s0-=min0;
				f1[i].s1-=min1;
				f2[j].s0-=min0;
				f2[j].s1-=min1;
				j++;
			}else{
				int min0=min(f1[i].s0,f2[j].s0),min1=min(f1[i].s1,f2[j].s1);
//				cout<<min0<<" "<<min1<<endl;
				ans+=min0+min1;
				f1[i].s0-=min0;
				f1[i].s1-=min1;
				f2[j].s0-=min0;
				f2[j].s1-=min1;
				i++;
				j++;
			}
//			printf("%d %d %d\n",i,f1[i].s0,f1[i].s1);
		}
		printf("%d\n",ans);
	}
	
	
	
	
	
	return 0;
}
/*
1
10
1010101010
0101010110
1100110011
0010101011
*/

回复

4 条回复,欢迎继续交流。

正在加载回复...