CF2030D QED's Favorite Permutation 题解

题目传送门

前置知识

差分

解法

对于移动,我们可以无脑进行交换来保证移动,然后将中途交换的位置再交换回去。

通过手摸不难发现,\(p_{i}\) 能移动到 \(i\) 当且仅当 \(s_{\min(i,p_{i}) \sim \max(i,p_{i})}\) 中不含有 LR 子串。

反向考虑,即 LR 子串不被上述区间包含,差分判断即可。

代码

ll a[200010],d[200010];
char s[200010];
int main()
{
	ll t,n,m,x,sum,i,j; 
	cin>>t;
	for(j=1;j<=t;j++)
	{
		cin>>n>>m;
		sum=0;
		for(i=1;i<=n;i++)
		{
			cin>>a[i];
			d[min(a[i],i)]++;
			d[max(a[i],i)]--;
		}
		for(i=1;i<=n;i++)
		{
			d[i]+=d[i-1];
		}
		cin>>(s+1);
		for(i=1;i<=n-1;i++)
		{
			if(s[i]=='L'&&s[i+1]=='R')
			{
				sum+=(d[i]!=0);
			}
		}
		for(i=1;i<=m;i++)
		{
			cin>>x;
			if(s[x]=='L')
			{
				s[x]='R';
				if(x+1<=n&&s[x+1]=='R')
				{
					sum-=(d[x]!=0);
				}
				if(x-1>=1&&s[x-1]=='L')
				{
					sum+=(d[x-1]!=0);
				}
			}
			else
			{
				s[x]='L';
				if(x+1<=n&&s[x+1]=='R')
				{
					sum+=(d[x]!=0);
				}
				if(x-1>=1&&s[x-1]=='L')
				{
					sum-=(d[x-1]!=0);
				}
			}
			if(sum!=0)
			{
				cout<<"No"<<endl;
			}
			else
			{
				cout<<"Yes"<<endl;
			}
		}
		for(i=1;i<=n;i++)
		{
			d[i]=0;
		}
	}
	return 0;
}
posted @ 2024-11-10 14:17  hzoi_Shadow  阅读(21)  评论(0编辑  收藏  举报
扩大
缩小