suxxsfe

一言(ヒトコト)

CF1221E Game With String

https://codeforces.com/problemset/problem/1221/E

给定由 X. 组成的字符串,先手每次可以选择长度为 \(a\) 的全 . 子串变成 X,后手每次可以选择长度为 \(b\) 的全 . 子串变成 X
问谁必胜
\(n\le 3\times 10^5\),保证 \(a>b\)

把每个极长的全 . 子串拿出来分别考虑
若存在某子串长度在 \([b,a)\) 中,则后手必胜,考虑去除掉这个子串,若某时刻先手选完以后后手不能选了,后手就选这个长度 \([b,a)\) 的,此时轮到先手一定不能再选

现在讨论不存在长度 \([b,a)\) 的子串,那么后手一定想要通过操作得到这样的子串
若存在某子串长度在 \([2b,\infty)\) 中,那么后手可以通过一部操作得出一个长度在 \([b,a)\) 中的子串(或者说直接操作出一个长度为 \(b\) 的就行)

  • 若这种子串多余一个,那么后手必胜
  • 若这种子串只有一个,那么先手可以尝试挽救一下
    • 不好直接讨论,于是枚举先手把这个串通过一次操作分割成了 \(p,q\),若存在 \([b,a)\)\([2b,\infty)\) 长度的,必然不行,否则只剩下 \(1\)\(2\) 个长度在 \([a,2b)\) 中的
    • 那么再加上原来的长度在 \([a,2b)\) 中的子串,设共 \(x\) 个,这些串只能被先后获后手操作仅一次,则先手必胜当且仅当 \(x\) 奇数
  • 若不存在这种子串,那么若长度在 \([a,2b)\) 中的子串有偶数个,则后手胜,否则先手胜
#define N 300006
char s[N];
int main(){int $=read();while($--){
	int a=read(),b=read();read(s+1);
	int n=std::strlen(s+1);
	int _b=0,_ab=0,_a=0,_alen=0;
	for(int i=1;i<=n;i++)if(s[i]=='.'){
		int j=i;while(s[j]=='.') j++;
		int len=j-i;
		if(len<b);
		else if(len<a) _b=1;
		else if(len<b<<1) _ab++;
		else _a++,_alen=len;
		i=j;
	}
	if(_b||_a>1) write("nO\n");
	else if(!_a) write((_ab&1)?"yEs\n":"nO\n");
	else{
		for(int p=0,q;_alen-p-a>=0;p++){
			q=_alen-p-a;
			if((p>=b<<1)||(q>=b<<1)) continue;
			if((p>=b&&p<a)||(q>=b&&q<a)) continue;
			if(!((_ab+(p>=b)+(q>=b))&1)) goto YES;
		}
		write("nO\n");continue;
		YES:write("yEs\n");
	}
}
	return SUC_RETURN;
}
posted @ 2021-11-12 10:57  suxxsfe  阅读(47)  评论(0)    收藏  举报