Codeforces Round #470-E-Picking Strings(想法题)


题意:给你一个串s和一个串t,然后有t次查询,每次查询输入四个数,问你第一个串中从x到y这一段能否通过操作变成第二个串的xx到yy这一段,具体有四种操作,每种操作次数和次序随意。

(1)A->BC  (2)B->AC  (3)C->AB  (4)AAA->空串

题解:我们仔细分析一下这四种操作,首先根据2和3我们很容易发现B和C是等价的,可以相互转换,通过2,3,4这三种操作可以发现我们可以将所有B和C之前的A全部删掉或者剩余任意数量的A,然后根据1,2,3我们发现每一个B或者C都能产生多出来一个BC(因为BC等价,所以BC,CB我就统称为BC了),根据以上我们发现的信息来解决这道题。

首先我们对于两个串的子段,我们可以把其B,C之前的A全部去掉,但是要注意末尾的所有A不能删,因为删的话会多出来B或者C,剩下的我们列举出所有不能转化的情况即可。

以下为所有不能转化的情况:

1.第一个串的B和C的数量多于第二个串(B和C只会增多不会减小)

2.第一个串的B和C的数量比第二个串少奇数个(因为每个B或者C只能多产出个BC,也就是每次多偶数个)

3.第一个串末尾的A多于第二个串末尾的A(A只会减小不会增多)

4.两个串的B和C的数量相等,但是两串末尾A的数量差不是3的倍数(只有三个A能消成空串)

5.特判第一个串B和C数量是0的情况并且第而个串的B和C数量不是0个,因为此时这两个串的末尾A的个数就不能再相等了,不然就不能和转化了。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 100005
int sm1[maxn],sm2[maxn],sum1[maxn],sum2[maxn];
char s1[maxn],s2[maxn];
int main(void)
{
	int T,x,y,xx,yy;
	scanf("%s%s",s1+1,s2+1);
	for(int i=1;s1[i]!='\0';i++)
	{
		if(s1[i]=='A')
			sm1[i]=sm1[i-1]+1;
		sum1[i]=sum1[i-1]+(s1[i]!='A');
	}
	for(int i=1;s2[i]!='\0';i++)
	{
		if(s2[i]=='A')
			sm2[i]=sm2[i-1]+1;
		sum2[i]=sum2[i-1]+(s2[i]!='A');
	}
	scanf("%d",&T);
	while(T--)
	{
		int ans=1;
		scanf("%d%d%d%d",&x,&y,&xx,&yy);
		int x1=min(y-x+1,sm1[y]);
		int x2=min(yy-xx+1,sm2[yy]);
		int y1=sum1[y]-sum1[x-1];
		int y2=sum2[yy]-sum2[xx-1];
		if(y1>y2 || y1<y2 && (y1+y2)%2 || x1<x2)
			ans=0;
		if(y1==y2 && x1%3!=x2%3 || y1==0 && x1==x2 && y1!=y2)
			ans=0;
		printf("%d",ans);
	}
	printf("\n");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值