zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    老婆和老媽同時掉在了水裡终于有答案了
    js对象序列化为json字符串
    基于jQuery的单据输入
    重发我的 HTML单据输入控件
    Spring MVC 实现REST风格API版本控制
    匿名方法和Lambda 表达式
    委托的定义和委托的实例化和使用
    LINQ进阶
    C#3.0的新特性
    使用 var 和 object 声明变量有什么区别?
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Contest20190725T1.html
Copyright © 2011-2022 走看看