Codeforces947D. Picking Strings

$n \leq 100000,m \leq 100000$,给长度$n$的字符串$s$和$m$的字符串$t$,只含ABC。定义串$a$可以经过任意次如下操作变成其他串。

现在$q \leq 100000$个询问每次给俩串各指定一个子串,问串$s$的子串能否变成串$t$的子串。

这个题叫细节题,送tourist下榜的。。极其恐怖。更恐怖的是他看起来是模拟题,而且pretest极弱,鬼都不知道自己错哪,先给场上AC的各位大佬献个膝盖。

好开始。首先有重要性质:$B->AC->AAB->AAAC->C$,$C->AB->AAC->AAAB->B$,所以$B=C$,且$AB->B$,因此把$C$看成$B$。而又$B->AC$,$A->BC$,得$B->AB$,$A->BB$,因此$B$前的$A$可以自由增减,且$A$可炸成$BB$。因此把目光投到后缀中的$A$。

首先如果目标串$B$比原始串少,由于$B$无法凭空消失,因此死。

如果$t$中有后缀$A$,$s$是无法凭空制造后缀$A$的,因此必须保留至少同样的数量,否则死。

如果有多出来的$A$,可以炸成$B$,也可三个三个消掉。那就看情况,如果目标串中的$B$和原始串一样,那就不得不三个三个消掉;如果目标串$B$比原始串多,那原始串要么得至少有个$B$,要么得炸一个$A$,您可能想说,不是肯定至少有个$A$或$B$吗不然串就空了那问个毛线,告诉您,这里的$A$是指抵消掉后缀后的!!

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 //#include<time.h>
 6 //#include<complex>
 7 #include<algorithm>
 8 #include<stdlib.h>
 9 using namespace std;
10 
11 int n,m,q;
12 #define maxn 200011
13 char s[maxn],t[maxn];
14 int ms[maxn],mt[maxn],sums[maxn],sumt[maxn];
15 int main()
16 {
17     scanf("%s%s",s+1,t+1);
18     n=strlen(s+1); m=strlen(t+1);
19     for (int i=1;i<=n;i++) sums[i]=sums[i-1]+(s[i]!='A'),ms[i]=s[i]=='A'?ms[i-1]+1:0;
20     for (int i=1;i<=m;i++) sumt[i]=sumt[i-1]+(t[i]!='A'),mt[i]=t[i]=='A'?mt[i-1]+1:0;
21     scanf("%d",&q);
22     while (q--)
23     {
24         int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
25         int ss=sums[y1]-sums[x1-1],tt=sumt[y2]-sumt[x2-1];
26         if (((ss&1)^(tt&1)) || ss>tt) {putchar('0'); continue;}
27         int aa=min(ms[y1],y1-x1+1)-min(mt[y2],y2-x2+1);
28         if (aa<0) {putchar('0'); continue;}
29         if (tt==ss)
30         {
31             if (aa%3) putchar('0');
32             else putchar('1');
33         }
34         else
35         {
36             if (aa || ss) putchar('1');
37             else putchar('0');
38         }
39     }
40     return 0;
41 }
View Code

 

posted @ 2018-03-11 19:31  Blue233333  阅读(313)  评论(0编辑  收藏  举报