[CF1508A] Binary Literature

前言

练习赛的时候降智写了一车面包锅,赛后一写就过。

题目

洛谷

CF

题目大意:

给定一个正整数 \(n\),接着输入三个长度为 \(2n\) 的01字符串,要求构造一个长度不超过 \(3n\) 的字符串使得至少给定的两个串为你构造的串的子序列

多组数据,\(\sum n\le 10^5\)

讲解

其实这道题还是比较好想的。

我们发现如果其中两个串的最长公共子序列能够达到 \(n\),那么我们将剩下的都按对应的位置插入进去,就可以构造出合法解。

根据鸽巢原理可知一个长度为 \(2n\) 的01字符串,一定会使得0或1达到半数。

而题目给了三个串,那么一定会有两个串使得0或1都达到半数,随便写写就好。

注意数组不要开小了。

代码

又丑又长。

bool check(int x,int y)
{
	int cnt1 = 0,cnt2 = 0;
	for(int i = 1;i <= 2*n;++ i) 
	{
		if(a[x][i] == '0') cnt1++;
		if(a[y][i] == '0') cnt2++;
	}
	if(cnt1 >= n && cnt2 >= n)
	{
		int MIN = Min(cnt1,cnt2),now1 = 1,now2 = 1;
		for(int i = 1;i <= MIN;++ i)
		{
			while(a[x][now1] != '0') putchar(a[x][now1]),now1++;
			while(a[y][now2] != '0') putchar(a[y][now2]),now2++;
			putchar('0');
			now1++;
			now2++;
		}
		for(int i = now1;i <= 2*n;++ i) putchar(a[x][i]);
		for(int i = now2;i <= 2*n;++ i) putchar(a[y][i]);
		putchar('\n');
		return 1;
	}
	cnt1 = 2*n - cnt1; cnt2 = 2*n - cnt2;//1的个数
	if(cnt1 >= n && cnt2 >= n) 
	{
		int MIN = Min(cnt1,cnt2),now1 = 1,now2 = 1;;
		for(int i = 1;i <= MIN;++ i)
		{
			while(a[x][now1] != '1') putchar(a[x][now1]),now1++;
			while(a[y][now2] != '1') putchar(a[y][now2]),now2++;
			putchar('1');
			now1++;
			now2++;
		}
		for(int i = now1;i <= 2*n;++ i) putchar(a[x][i]);
		for(int i = now2;i <= 2*n;++ i) putchar(a[y][i]);
		putchar('\n');
		return 1;
	}
	return 0;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	for(int T = Read(); T ;-- T)
	{
		n = Read();
		for(int i = 0;i < 3;++ i) scanf("%s",a[i]+1);
		bool f = 1;
		for(int i = 0;i < 3 && f;++ i)//其实不需要这么多次
			for(int j = 0;j < 3 && f;++ j)
				if(i != j && check(i,j))
					f = 0;
	}
	return 0;
}
posted @ 2021-04-18 12:15  皮皮刘  阅读(78)  评论(0编辑  收藏  举报