Codeforces gym 101142 B

100 篇文章 0 订阅
23 篇文章 1 订阅

简单构造题。
首先转化为有 x x x个人左右都是男生, y y y个人左右都是女生。接着可以发现这相当于隔 2 2 2个位置的人之间,有 x x x组都是男生, y y y组都是女生。
先考虑另一个问题:一个长为 n n n的环,有 x x x对相邻的人都是男生, y y y对相邻的人都是女生,问有解条件。显然需要满足 x + y ≤ n x+y\leq n x+yn且与 n n n奇偶性相同,且 x + y = n x+y=n x+y=n的话当且仅当 x = n x=n x=n y = n y=n y=n时有解(全为男生或全为女生)。如果 x + y ≤ n − 2 x+y\leq n-2 x+yn2且与 n n n奇偶性相同,那么先安排 x + 1 x+1 x+1个男生,再安排 y + 1 y+1 y+1个女生,后面男女生交替即可。
现在如果 n n n是奇数,容易重标号得到上面的问题。 n n n是偶数的话相当于有两个长为 n 2 \frac{n}{2} 2n的环,比较简单的处理是枚举在第一个环上相邻男生的对数( ≤ x \leq x x),显然接下来会在奇偶性满足条件的前提下,尽可能最大化第一个环上相邻女生的对数( ≤ y \leq y y),这样也可以知道另一个环的情况了。
时间复杂度为 O ( n ) \mathcal O(n) O(n)

#include <bits/stdc++.h>

using namespace std;

char ans[100005];

int main() {
  freopen("boysgirls.in","r",stdin);
  freopen("boysgirls.out","w",stdout);
  int n,x,y;
  scanf("%d%d%d",&n,&x,&y);
  x=n-x;y=n-y;
  swap(x,y);
  /*if (n==2) {
  	if (x+y!=2) {
  		puts("Impossible");
  		return 0;
	  }
	for(int i=1;i<=x;i++) putchar('B');
	for(int i=1;i<=y;i++) putchar('G');
	printf("\n");
	return 0;
  }*/
  if (n&1) {
  	if (!((x+y)&1)) {
  		puts("Impossible");
  		return 0;
	  }
	if (!x&&y==n) {
		for(int i=1;i<=n;i++) putchar('G');
	    printf("\n");
		return 0;
	}
	if (!y&&x==n) {
		for(int i=1;i<=n;i++) putchar('B');
		printf("\n");
		return 0;
	} 
	if (x+y>=n) {
		puts("Impossible");
		return 0;
	}
	for(int i=1;i<=x+1;i++) ans[(2*i-1)%n+1]='B';
	for(int i=1;i<=y+1;i++) ans[(2*(x+1+i)-1)%n+1]='G';
	for(int i=1;i<=n-x-y-2;i++) ans[(2*(x+y+2+i)-1)%n+1]=((i&1)?'B':'G');
	puts(ans+1);
  }
  else {
  	if ((x+y)&1) {
  		puts("Impossible");
  		return 0;
	  }
	if (!x&&y==n) {
		for(int i=1;i<=n;i++) putchar('G');
	    printf("\n");
		return 0;
	}
	if (!y&&x==n) {
		for(int i=1;i<=n;i++) putchar('B');
		printf("\n");
		return 0;
	} 
	for(int i=0;i<=min(n/2,x);i++) {
		int j=min(y,max(0,n/2-i-2));
		if (((i+j)^(n/2))&1) {
			if (!j) continue;
			else j--;
		}
		int u=x-i,v=y-j;
		if (u+v>n/2||(u+v==n/2&&u&&v)) continue;
		if (i==n/2) {
			for(int k=1;k<=n/2;k++) ans[2*k]='B'; 
		}
		else if (j==n/2) {
		    for(int k=1;k<=n/2;k++) ans[2*k]='G';
		}
		else {
			for(int k=1;k<=i+1;k++) ans[2*k]='B';
			for(int k=1;k<=j+1;k++) ans[2*(i+1+k)]='G';
			for(int k=1;k<=n/2-i-j-2;k++) ans[2*(i+j+2+k)]=((k&1)?'B':'G');
		}
		if (u==n/2) {
			for(int k=1;k<=n/2;k++) ans[2*k-1]='B'; 
		}
		else if (v==n/2) {
		    for(int k=1;k<=n/2;k++) ans[2*k-1]='G';
		}
		else {
			for(int k=1;k<=u+1;k++) ans[2*k-1]='B';
			for(int k=1;k<=v+1;k++) ans[2*(u+1+k)-1]='G';
			for(int k=1;k<=n/2-u-v-2;k++) ans[2*(u+v+2+k)-1]=((k&1)?'B':'G');
		}
		puts(ans+1);
		return 0;
	}
	puts("Impossible");
  }
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值