线段树维护区间括号序列合法性
[ABC223F] Parenthesis Checking
维护区间和以及前缀最小值, 对于一个区间括号序列合法判断方法 :
视 ' ( ' 为 1 , ' ) ' 为 -1
那么一段区间括号序列合法就是:
1.该段区间和为 0
2.对于这段中每个位置的前缀和 u 都要满足 u >= 0

#include<bits/stdc++.h> using namespace std; #define endl "\n" typedef long long ll; const int N = 2e5 + 10; int v[N], all, minx; struct Info { int sum, minn; }; struct node{ Info info; } Seg[N * 4]; Info operator + (const Info &l, const Info &r) { Info ans; ans.sum = l.sum + r.sum; ans.minn = min(l.minn, l.sum + r.minn); return ans; } void pushup(int id) { Seg[id].info = Seg[id * 2].info + Seg[id * 2 + 1].info; } void build(int id, int l, int r) { if(l == r) { Seg[id].info.sum = Seg[id].info.minn = v[l]; return; } int mid = (l + r) >> 1; build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r); pushup(id); } void modify(int id, int l, int r, int pos, int val) { if(l == r) { Seg[id].info.sum = Seg[id].info.minn = val; return; } int mid = (l + r) >> 1; if(pos <= mid) modify(id * 2, l, mid, pos, val); else modify(id * 2 + 1, mid + 1, r, pos, val); pushup(id); } void qurey(int id, int l, int r, int x, int y) { if(l >= x && r <= y) { minx = min(minx, all + Seg[id].info.minn); all += Seg[id].info.sum; return; } int mid = (l + r) >> 1; if(x <= mid) qurey(id * 2, l, mid, x, y); if(y > mid) qurey(id * 2 + 1, mid + 1, r, x, y); } int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n, q; cin >> n >> q; string s; cin >> s; for(int i = 0; i < n; i++) { if(s[i] == '(') v[i + 1] = 1; else v[i + 1] = -1; } build(1, 1, n); while(q--) { int op, l, r; cin >> op >> l >> r; if(op == 1) { if(s[l - 1] == s[r - 1]) continue; if(s[l - 1] == '(') modify(1, 1, n, l, -1), modify(1, 1, n, r, 1); else modify(1, 1, n, l, 1), modify(1, 1, n, r, -1); swap(s[l - 1], s[r - 1]); } else { minx = INT_MAX, all = 0; qurey(1, 1, n, l, r); // cout << all << ' ' << minx << endl; if(all == 0 && minx == 0) cout << "Yes" << endl; else cout << "No" << endl; } } return 0; }
合法性判断和上题一样, 对于嵌套括号其实就是前缀最大值,此时我们只需要线段树多维护一个前缀最大值即可

#include<bits/stdc++.h> using namespace std; #define endl "\n" #define int long long typedef long long ll; const int N = 1e6 + 10; struct Info { int sum, minn, maxn; }; struct node{ Info info; } Seg[N * 4]; Info operator + (const Info &l, const Info &r) { Info ans; ans.sum = l.sum + r.sum; ans.minn = min(l.minn, l.sum + r.minn); ans.maxn = max(l.maxn, l.sum + r.maxn); return ans; } void pushup(int id) { Seg[id].info = Seg[id * 2].info + Seg[id * 2 + 1].info; } void modify(int id, int l, int r, int pos, int val) { if(l == r) { Seg[id].info.sum = Seg[id].info.minn = Seg[id].info.maxn = val; return; } int mid = (l + r) >> 1; if(pos <= mid) modify(id * 2, l, mid, pos, val); else modify(id * 2 + 1, mid + 1, r, pos, val); pushup(id); } signed main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n; cin >> n; string s; cin >> s; int pos = 1, maxpos = 1; for(int i = 0; i < n; i++) { maxpos = max(maxpos, pos); if(s[i] == 'R') pos++; if(s[i] == 'L') pos--; maxpos = max(maxpos, pos); } pos = 1; for(int i = 0; i < n; i++) { if(s[i] == 'R') { pos++; } else if(s[i] == 'L') { if(pos != 1) pos--; } else if(s[i] == '(') { modify(1, 1, maxpos, pos, 1); } else if(s[i] == ')') { modify(1, 1, maxpos, pos, -1); } else { modify(1, 1, maxpos, pos, 0); } if(Seg[1].info.sum == 0 && Seg[1].info.minn == 0) { cout << Seg[1].info.maxn << ' '; } else { cout << -1 << ' '; } } return 0; }
板子题, 最简单的一题

#include<bits/stdc++.h> using namespace std; #define endl "\n" #define int long long typedef long long ll; const int N = 3e4 + 10; int minx, all, v[N]; struct Info { int sum, minn, maxn; }; struct node{ Info info; } Seg[N * 4]; Info operator + (const Info &l, const Info &r) { Info ans; ans.sum = l.sum + r.sum; ans.minn = min(l.minn, l.sum + r.minn); return ans; } void pushup(int id) { Seg[id].info = Seg[id * 2].info + Seg[id * 2 + 1].info; } void build(int id, int l, int r) { if(l == r) { Seg[id].info.sum = Seg[id].info.minn = v[l]; return; } int mid = (l + r) >> 1; build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r); pushup(id); } void modify(int id, int l, int r, int pos, int val) { if(l == r) { Seg[id].info.sum = Seg[id].info.minn = val; return; } int mid = (l + r) >> 1; if(pos <= mid) modify(id * 2, l, mid, pos, val); else modify(id * 2 + 1, mid + 1, r, pos, val); pushup(id); } signed main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); for(int T = 1; T <= 10; T++) { cout << "Test " << T << ":" << endl; int n; cin >> n; string s; cin >> s; s = " " + s; for(int i = 1; i <= n ; i++) { if(s[i] == '(') v[i] = 1; else v[i] = -1; } build(1, 1, n); int q; cin >> q; while(q--) { int op; cin >> op; if(op == 0) { if(Seg[1].info.sum == 0 && Seg[1].info.minn >= 0) cout << "YES" << endl; else cout << "NO" << endl; } else { if(s[op] == '(') { modify(1, 1, n, op, -1); s[op] = ')'; } else { modify(1, 1, n, op, 1); s[op] = '('; } } } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】