Codeforces Round #658 (Div. 1)

A1.Prefix Flip (Easy Version)
https://codeforces.com/contest/1381/problem/A1
A2.Prefix Flip (Hard Version)
https://codeforces.com/contest/1381/problem/A2
大意是给两个仅由01组成的字符串a和b,长均为n,允许如下操作:
对一个字符串的1~ i i i位分别取反后翻转 1 ~ i i i位的位置。
举例,对100的1~2位操作后结果为100。
其中分别取反后为010,翻转后为100。
Easy Version和Hard Version的区别是字符串长度不同。
要求输出一个操作序列使得a串变成b串,序列长度不得超过2n,序列中每个元素x代表对a串的1~x位进行操作。
显然我们可以通过对每个串进行至多n-1次操作将a和b串变成全0或者全1,这两个串变成全0/全1后如果不相等那么再追加1次对整个串的操作即可,总操作次数不超过2n-1次。
输出时,顺序输出使a串变为全0/全1的操作步骤,再倒序输出使b串变为全0/全1的步骤即可。

#include
#include
#include
#include
#include
#include
#define MOD 1000000007
using namespace std;
int t,ans[2][100005],cot[2];
char a[100005],b[100005];
int n;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		scanf("%s",a+1);
		scanf("%s",b+1);
		cot[0]=cot[1]=0;
		for(int i=1;i<=n;i++)
		{
			if(a[i]!=a[1])
			{
				cot[0]++;
				ans[0][cot[0]]=i-1;
				a[1]='1'-a[1]+'0';
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(b[i]!=b[1])
			{
				cot[1]++;
				ans[1][cot[1]]=i-1;
				b[1]='1'-b[1]+'0';
			}
		}
		if(a[1]!=b[1]) 
		{
			cot[0]++;ans[0][cot[0]]=n;
		}
		printf("%d",cot[0]+cot[1]);
		for(int i=1;i<=cot[0];i++) printf(" %d",ans[0][i]);
		for(int i=cot[1];i;i--) printf(" %d",ans[1][i]);
		printf("\n");
	}
	return 0;
}

B.Unmerge
题意是说用归并排序的方法对两个长为 n n n的数组进行排序(但这两个数组不一定有序),之后得到一个长为2 n n n的数组。
现在给出一个长为2 n n n的数组,问能否构造出两个长为 n n n的数组使得归并排序后得到这个长为2 n n n的数组。但只问能否构造而不要求具体构造出这两个数组。长为2 n n n的数组保证是一个1到2 n n n的全排列。

这题乍一看是个构造题,但实际上是个dp,或者说需要用到dp的思想。
不妨设输入数组为a[], a i + x a_{i+x} ai+x a i a_{i} ai之后第一个大于 a i a_i ai的数,假设可以构造这两个数组,那么根据归并排序的原理,我们可以推断 a i a_{i} ai ~ a i + x − 1 a_{i+x-1} ai+x1全部属于同一个数组。
那么我们按照这个方法将输入数组分成若干段,记录每段的长度,问题就转化成了能否用这些段构造出一个长为 n n n的数组(可以构造的话,剩下的部分显然可以用来构造另一个长为 n n n的数组),然后类似完全背包的解法就行了。

#include
#include
#include
#include
#include
#include
#define MOD 1000000007
using namespace std;
typedef struct data{
	int num,pos;
}data;
data p[4005];
int d[4005],cot;
int t,n;
int dp[2005];
int cmp(data a,data b)
{
	return a.num>b.num;
}
int main()
{
	scanf("%d",&t);
	dp[0]=1;
	cot=0;
	while(t--)
	{
		scanf("%d",&n);
		n*=2;
		cot=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&p[i].num);
			p[i].pos=i;
		}
		sort(p+1,p+n+1,cmp);
		int pos=n+1;
		for(int i=1;i<=n;i++)
		{
			if(p[i].pos<pos)
			{
				cot++;d[cot]=pos-p[i].pos;pos=p[i].pos;
			}
		}
		n/=2;
		for(int i=1;i<=cot;i++)
		for(int j=n;j;j--)
		{
			if(j>=d[i])
			{
				if(dp[j-d[i]]) dp[j]=1;
			}else break;
		}
		if(dp[n])
		{
			printf("YES\n");
		}else
		{
			printf("NO\n");
		}
		for(int i=1;i<=n;i++)
		{
			dp[i]=0;
		}
	}
	return 0;
}

虽然C题和C题之后的都不会写,但是这场我还是上分了,快乐

你可能感兴趣的:(题解(按比赛),CodeForces)