【2019.7.25 NOIP模拟赛 T1】变换(change)(思维+大分类讨论)

几个性质

我们通过推式子可以发现:

[B⇒AC⇒AAB⇒AAAC⇒C ]

[C⇒AB⇒AAC⇒AAAB⇒B ]

也就是说:

性质一: (B,C)可以相互转换。

则我们再次推式子可以发现:

[B⇒AC⇒AB ]

也就是说:

性质二:(B)(C)之前可以任意加或减少若干个(A)

同样,我们可以发现:

[A⇒BC⇒BB ]

也就是说:

性质三:(B)(C)之前可以任意加偶数个(B)(C)

有了这些性质,你以为就做完了吗?

闪指导(hl666)曰:“不!现在才刚刚开始!”

分类讨论

由上面性质一可见,我们可以把所有的(C)都看成(B),这样就只有两种字母了。

接下来我们讨论哪些情况是无解的:

  • 若两个区间中(B)的数量的奇偶性不同,就无解(因为只能加偶数个(B))。

  • 若第一个区间中(B)的数量大于第二个区间中(B)的数量,就无解(因为无法减少(B)的数量)。

    但这里还需要注意,若出现如(BAA)(BA)这样的情况,即二者(B)数量相同,第一个区间中(A)的数量大于第二个区间中(A)的数量,且差值不为(3)的倍数(此时可以直接消(A)),就无解(因为要消去末尾(A)必须把某个(A)变成(BB),第一个区间中(B)的数量就大于了第二个区间中(B)的数量)。

  • 若第一个区间中末尾(A)的数量小于第二个区间中末尾(A)的数量,就无解(因为无法增加末尾(A)的数量)。

    这里同样要注意,若出现如(A)(BBA)这样的情况,即二者某位(A)数量相同,第一个区间中没有(B)且第二个区间中有(B),就无解(因为必须要消末尾(A)来产生(B),第一个区间中末尾(A)的数量就小于了第二个区间中末尾(A)的数量)。

剩余情况就是有解了。

代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 5000000
using namespace std;
int n,m,s[N+5][2],p[N+5][2];char s1[N+5],s2[N+5];
class FastIO
{
	private:
		#define FS 100000
		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
		#define tn (x<<3)+(x<<1)
		#define D isdigit(c=tc())
		char c,*A,*B,FI[FS];
	public:
		I FastIO() {A=B=FI;}
		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
		Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
		I void reads(char *x) {RI t=0;W(isspace(c=tc()));W(x[++t]=c,!isspace(c=tc())&&~c);}
}F;
int main()
{
	freopen("change.in","r",stdin),freopen("change.out","w",stdout);
	RI Qt,i,x1,y1,x2,y2,t1,t2,p1,p2;F.reads(s1),F.reads(s2),n=strlen(s1+1),m=strlen(s2+1);//读入
	for(i=1;i<=n;++i) s[i][0]=s[i-1][0],s1[i]^65?(++s[i][0],p[i][0]=0):(p[i][0]=p[i-1][0]+1);//求第一个字符串每个位置B数量的前缀和以及每个位置前连续出现的A的个数
	for(i=1;i<=m;++i) s[i][1]=s[i-1][1],s2[i]^65?(++s[i][1],p[i][1]=0):(p[i][1]=p[i-1][1]+1);//求第二个字符串每个位置B数量的前缀和以及每个位置前连续出现的A的个数
	F.read(Qt);W(Qt--) F.read(x1,y1,x2,y2),//读入询问
		t1=s[y1][0]-s[x1-1][0],t2=s[y2][1]-s[x2-1][1],//差分求出两个区间中B的数量
		p1=min(p[y1][0],y1-x1+1),p2=min(p[y2][1],y2-x2+1),//求出末尾A的数量,注意向区间长度取min
		putchar(((t1^t2)&1||t1+2*(p1>p2&&(p1-p2)%3)>t2||p1-(!t1&&t2)<p2)?'0':'1');//输出判断结果
	return 0;
}
原文地址:https://www.cnblogs.com/chenxiaoran666/p/Contest20190725T1.html