[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却不会。

浙公网安备 33010602011771号