经典问题:区间最长合法括号子序列长度

传送门
可以用线段树维护,\(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;
}
posted @ 2025-09-11 19:21  孤枕  阅读(6)  评论(0)    收藏  举报