ARC166A的题解

略带一点思维吧。

个人认为比 B 难想。

先来考虑弱化版的题面:


Case 1

如果 X 串和 Y 串都没有字母 C,如何判断是否有解?

观察操作,我们能发现这个操作的本质实际上是让一个位于前面的字母 A 挪到其后面的任意的位置,并且前后两个 A 的相对位置不会发生改变。

所以,如果:

  1. X 串与 Y 串长度相等。

  2. XA 的数量与 Y 串中 A 的数量相等。

  3. X 串和 Y 串中的 A 从前往后标号,每一组 X 串中的 A 的位置比其对应标号的 YA 的位置靠前。

以上三种情况均满足时有解。

解释一下第三种情况。

假设:

X:ABAABBY:ABBABA

标号后为:

1 2 3 4 5 6 X:ABAABB1    2 3       Y:ABBABA1        2    3

将对应标号的 A 的位置写出来为:

X:1 3 4Y:1 4 6

我们发现,相同的标号,X 串的位置都比 Y 串的位置前。

所以这种情况下就是有解的。

再比如:

X:ABABABY:ABAABB

标号后为:

1 2 3 4 5 6 X:ABABAB1    2     3   Y:ABAABB1     2 3       

将对应标号的 A 的位置写出来为:

X:1 3 5Y:1 3 4

我们发现,相同的标号,第三组 X 串的位置比 Y 串的位置后。

所以这种情况下就是无解的。


Case 2

升级一下:

如果 X 串有 CY 串没有 C,如何判断是否有解?

根据 Case 1,我们知道首先 X 串和 YA 的数量要相等。

贪心地考虑,如果我们要使得 X 串能变成 Y 串,我们 A 越前越好。剩下的 C 就全部变成 B 就行了。

所以我们就能得出这一部分的有解的情况:

  1. X 串与 Y 串长度相等。

  2. XA 的数量加上 C 的数量要超过 Y 串的 A 的数量。

  3. XA 的数量不能超过 Y 串的 A 的数量。

  4. 若我们贪心地把 X 串用 C 来凑 A 使得 X 串和 Y 串的 A 的数量相等后,需要满足 Case 1 的条件 3


Case 3

就是原题了。

我们发现,如果存在一个 i 使得 Xi 不为 CYiC 时一定无解。

去除掉这种无解的情况后,Y 串剩余的 C 一定都能在 X 串对应的位置找到 C

考虑到操作不能使得 C 的位置交换,所以这些 C 我们不能把它们变成 A 或者 B

此时,整个 X 串和 Y 串就被我们切割成若干段。

我们考虑每一段,此时问题就退化成 Case 2 的版本了。

单次询问时间复杂度 O(n)

#include<cstdio>
const int N=2e5+10;
int T;
int n;
char s[N],t[N];
int ss[N],tt[N];
bool check()
{
	for(int i=1;i<=n;i++)
		if(s[i]!='C'&&t[i]=='C') return 0;
	int x[N],tot=0;
	x[++tot]=1;
	for(int i=1;i<=n;i++)//切割
		if(t[i]=='C'&&i!=1&&i!=n) x[++tot]=i;
	x[++tot]=n;
	for(int i=1;i<tot;i++)
	{
		int l=x[i],r=x[i+1];
		if(t[l]=='C') l++;
		if(t[r]=='C') r--;
		int sa=0,sc=0,ta=0;
		for(int j=l;j<=r;j++)
		{
			if(s[j]=='A') sa++;
			if(s[j]=='C') sc++;
			if(t[j]=='A') tt[++ta]=j;
		}
		if(sa+sc<ta) return 0;
		if(sa>ta) return 0;
		sc=ta-sa,sa=0;//计算出需要用多少个 C 去变成 A
		for(int j=l;j<=r;j++)
		{
			if(s[j]=='A') ss[++sa]=j;
			if(s[j]=='C'&&sc) ss[++sa]=j,sc--;//贪心地填补 A
		}
		for(int j=1;j<=sa;j++)
			if(ss[j]>tt[j]) return 0;
	}
	return 1;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%s%s",&n,s+1,t+1);
		if(check()) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
posted @   osfly  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示