Bracket Walk

Bracket Walk

Created by LXC on Mon Feb 12 08:24:04 2024

https://codeforces.com/problemset/problem/1838/D

ranting: 2100

tag: data structures, greedy, strings

problem

  • 给你一个长度为 $n$ 的括号序列。
  • 你从括号序列的左端出发,可以向右走或者向左走(不能向左走到起点的外面)。
  • 有一个记录你走过括号的序列,即你每到达一个位置,上方的括号会被记录下来,加到这个记录你走过括号的序列的末尾。
  • 当你走到括号序列的最右端时,你可以走出括号序列并终止流程,此时你需要判断记录你走过括号的序列是否括号匹配。
  • 若存在一种走的方案,使得记录你走过括号的序列可以括号匹配,则称这个括号序列是“可行走的”。
  • 你有多次询问,每次询问会修改某一个位置的状态(左括号变成右括号,右括号变成左括号),你需要判断修改过后这个括号序列是否是“可行走的”。
  • 询问之间不互相独立,即每次询问会影响接下来的询问。

solution

对于串s如何判断能否可行走。

首先s的长度是奇数必定不可行走。

我们先去除前缀和后缀尽量多的()

最后得到((...))则可证明是可行走的。

除去...中已经匹配好的括号序列,多余的()都是偶数个,我们可以利用((增加偶数个(,利用))增加偶数个)

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

#include <bits/stdc++.h>
#define SINGLE_INPUT
#define ll long long
#define ull unsigned long long
#define N 500005
#define MOD 998244353
using namespace std;

template<class t,class u> ostream& operator<<(ostream& os,const pair<t,u>& p) {
return os<<'['<<p.first<<", "<<p.second<<']';
}
template<class t> ostream& operator<<(ostream& os,const vector<t>& v) {
os<<'['; int s = 1;
for(auto e:v) { if (s) s = 0; else os << ", "; os << e; }
return os<<']';
}
template<class t,class u> ostream& operator<<(ostream& os,const map<t,u>& mp){
os<<'{'; int s = 1;
for(auto [x,y]:mp) { if (s) s = 0; else os << ", "; os<<x<<": "<<y; }
return os<<'}';
}

void sol() {
int n, q;
cin >> n >> q;
string s;
cin >> s;
set<int> st;
for (int i=0; i<n; i++) {
if (s[i] == '(' && i%2) st.insert(i);
if (s[i] == ')' && i%2 == 0) st.insert(i);
}
while (q--) {
int x;
cin >> x;
x--;
if (s[x] == '(' && x%2 == 1 || s[x] == ')' && x%2 == 0) st.erase(x);
else st.insert(x);

if (s[x] == '(') s[x] = ')';
else s[x] = '(';

if (n%2) {
cout << "NO\n";
} else {
if (st.empty() || *st.begin()%2 == 1 && *st.rbegin()%2 == 0) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}

}
}

int main() {
cout << setprecision(15) << fixed;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifndef SINGLE_INPUT
int t;
cin >> t;
while (t--) {
sol();
}
#else
sol();
#endif
return 0;
}