经典问题:区间最长合法括号子序列长度
传送门
可以用线段树维护,\(ln\)表示当前区间无法匹配的左括号数量,\(rn\)表示当前区间无法匹配的右括号数量
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e6 + 10;
const int inf = 1e18 + 10;
string s;
int n,m;
struct node {
int ln,rn;
}nde[N];
node up(node ls,node rs) {
node res = {0,0};
res.ln = ls.ln - min(ls.ln,rs.rn) + rs.ln;
res.rn = rs.rn - min(rs.rn,ls.ln) + ls.rn;
return res;
}
void build(int k,int l,int r) {
if(l == r) {
if(s[l] == '(') nde[k].ln++;
else if(s[l] == ')') nde[k].rn++;
return;
}
int mid = (l + r) >> 1;
build(k * 2,l,mid);
build(k * 2 + 1,mid + 1,r);
nde[k] = up(nde[k * 2],nde[k * 2 + 1]);
}
node query(int k,int l,int r,int x,int y) {
if(l >= x && r <= y)
return nde[k];
int mid = l + r >> 1;
node ls = {0,0},rs = {0,0};
if(mid >= x) ls = query(k * 2,l,mid,x,y);
if(mid < y) rs = query(k * 2 + 1,mid + 1,r,x,y);
return up(ls,rs);
}
void solve() {
cin >> s;
n = s.length();
s = ' ' + s;
build(1,1,n);
cin >> m;
while(m--) {
int l,r;
cin >> l >> r;
node res = query(1,1,n,l,r);
cout << r - l + 1 - res.ln - res.rn << '\n';
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t = 1;
//cin >> t;
while(t--) solve();
return 0;
}

浙公网安备 33010602011771号