[CF2224C] Zhily and Bracket Swapping 题解

[CF2224C] Zhily and Bracket Swapping 题解

题目传送门

题目大意

小明会给你两串括号序列,由左右括号组成。这里我们把第一串括号序列的第 \(i\) 个括号命名为 \(a_i\) ,第二串的第 \(i\) 个命名为 \(b_i\)

你可以交换两串序列中对应位置的括号,即可以交换 \(a_i\)\(b_j\) ,此时 \(i=j\)

问你任意次操作后能不能得到两串合法的括号序列。

括号序列合法的定义

多测,序列总长度 \(\le 2\times10^5\)

思路

感觉现在有一种无论看到什么题都想要用DP碾过去的想法。

发现带上转移就至少是个 \(O(n^2)\) 的算法了,而且优化也困难。

于是想到似乎能贪心一下。

按照栈弹出的思路理解括号序列,即左括号给当前层数+1,右括号-1,从头扫到尾的过程中全程层数非负且最后层数为0的括号序列为合法序列,于是发现:

在小明给的两个序列中 \(a_i=b_i\) 的位置中:两个序列的层数同增同减且题中操作对此无能为力,所以要想他们的层数都非负,最优解只能是使当前层数最小的那个最大。

于是,在小明给的两个序列中 \(a_i\neq b_i\) 的位置中,我们找出两个序列中层数较小的那个,把右括号换到它那里,最后判断这么操作后的序列最后层数是否为零就行。

代码

是个难想但好写的思维题。

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=2e5;
char a[N+10],b[N+10];
void work(){
	int n;
	scanf("%d",&n);
	scanf("%s%s",a+1,b+1);
	int stk1=0,stk2=0;
	for(int i=1;i<=n;i++){
		if(a[i]==b[i]){
			if(a[i]=='('){
				stk1++;
				stk2++;
			}else{
				stk1--;
				stk2--;
			}
		}else{
			if(stk1>stk2){
				stk1--;
				stk2++;
			}else{
				stk1++;
				stk2--;
			}
		}
		if(min(stk1,stk2)<0){
			printf("NO\n");
			return;
		}
	}
	if(stk1||stk2){
		printf("NO\n");
		return;
	}else{
		printf("YES\n");
		return;
	}
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		work();
	}
	return 0;
}

后记

这把感觉没发挥好,A和C几乎秒了但是B却不会。

posted @ 2026-05-07 13:24  Liyanx_ArtI  阅读(37)  评论(0)    收藏  举报