【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;
}
待到再迷茫时回头望,所有脚印会发出光芒