CF 947D 细节讨论

传送门
这题挂了一大波人,包括T神,直接结果就是CF万年不变的榜首终于换了人。233
现在看来,如果当时再仔细一点就黄了,可惜。

回到正题:首先很明显的是:
B->AC->AAB->AAAC->C
C->AB->AAC->AAAB->B

于是B和C本质上是等价的,可以把所有的C替换成B,得到:
A->BB
B->AB
AAA->empty

考虑从S串是否能到达T串,观察推导式的性质,可以发现:

T串末尾连续的A必然不是生成的,即S串末尾连续的A必然不少于T的;

由于 AB->AAB->AAAB->B ,故而在B前面的A的个数可以随意更改,于是除了末尾连续的A,前
面我们care的只有B的个数;

更进一步,在从S到T的过程中,B的个数只会增加和不变,而且若增加一定是增加两个,于是如果S的B的个数比T多或者不同奇偶,肯定是不行的。

S末尾的A个数大于等于T末尾A的个数,S的B的个数大于等于T的B的个数,S的B的个数与T的B的个数同奇偶,这样就够了么?

考虑以下的几个例子:

S:AAAA
T:A

S:AA
T:A

S:BBAA
T:BBA

S:A
T:BBA

答案依次为: 1 0 0 0

可以发现事情并不简单:
首先,我们观察1、2、3得出,如果末尾的A相差的不是3的倍数,S需要额外把一个A变成BB,B的个数增加显然不是什么好事,但是我们不得不这样做。更麻烦的是,对于满足上述条件的4来说,因为S原本没有B而T有B,必须把唯一的A拿去做B,而如果S和T都没有B,又是另一个故事了。如果继续讨论下去,将会陷入更麻烦的漩涡,我们先暂停,考虑一下简化方案。

首先,排除S末尾的A比T末尾的A少的情况。
考虑把T末尾这段A共同切掉,剩余的部分有三种特殊情况:
1.S和T都是空串,毫无疑问这种情况是可行的;
2.S是空串但T不是空串,因为T剩余部分最后一个是B,而S作为空串无法提供这个B,不可行;
3.S不是空串而T是空串,这种情况只有T剩余部分全是A并且长度是3的倍数才可行;

其余的情况就是S和T的剩余部分都不是空串,而且T的末尾一定是B。因为S至少要提供一个B,所以如果S剩余部分全是A或者S剩余部分末尾A不是3的倍数(全部消去),则不可避免地,S中的某个A要变成BB,计数+=2。最后,我们比较一下B的大小和奇偶性,就可以了。

代码:

#include <bits/stdc++.h>
using namespace std;
char s[100005],t[100005];
int sbpre[100005],tbpre[100005];
int sa[100005],ta[100005];
int n,m;
int main(){
    scanf("%s",s+1);
    scanf("%s",t+1);
    n=strlen(s+1);
    m=strlen(t+1);
    for(int i=1;i<=n;i++){
        if(s[i]=='C')s[i]='B';
        sbpre[i]=sbpre[i-1];
        if(s[i]=='B')sbpre[i]++;
    }
    for(int i=1;i<=m;i++){
        if(t[i]=='C')t[i]='B';
        tbpre[i]=tbpre[i-1];
        if(t[i]=='B')tbpre[i]++;
    }
    for(int i=1;i<=n;i++){
        if(s[i]!='A')sa[i]=0;
        else sa[i]=sa[i-1]+1;
    }
    for(int i=1;i<=m;i++){
        if(t[i]!='A')ta[i]=0;
        else ta[i]=ta[i-1]+1;
    }
    int T;
    scanf("%d",&T);
    while(T--){
        int l1,r1,l2,r2;
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        int len1=r1-l1+1;
        int len2=r2-l2+1;
        int ssa=min(sa[r1],len1);
        int tta=min(ta[r2],len2);
        int sb=sbpre[r1]-sbpre[l1-1];
        int tb=tbpre[r2]-tbpre[l2-1];
        if(ssa<tta){
            putchar('0');
        }
        else if(tta==len1&&tta==len2){
            putchar('1');
        }
        else if(tta==len2){
            if(ssa%3==tta%3&&ssa==len1)putchar('1');
            else putchar('0');
        }
        else if(tta==len1){
            putchar('0');
        }
        else {
            if(ssa==len1||ssa%3!=tta%3)sb+=2;
            if(sb%2==tb%2&&sb<=tb)putchar('1');
            else putchar('0');
        }
    }
}

猜你喜欢

转载自blog.csdn.net/mrbird_to_fly/article/details/79525780