[CF1508A] Binary Literature

前言

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

题目

洛谷

CF

题目大意:

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

多组数据,(sum nle 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('
');
		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('
');
		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;
}
原文地址:https://www.cnblogs.com/PPLPPL/p/14673168.html