把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【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;
}
posted @ 2019-07-26 20:35  TheLostWeak  阅读(190)  评论(0编辑  收藏  举报