1. 程式人生 > 其它 >cf380 C. Sereja and Brackets

cf380 C. Sereja and Brackets

題意:

給定括號串。m次詢問,每次回答 \([x,y]\) 中的最長合法括號子列長度

思路:

線段樹,維護 \([l,r]\) 中失配的左括號數量 \(L\) 和右括號數量 \(R\)

合併相鄰區間:左半區間未匹配的左括號 可以和 右半區間未匹配的右括號 抵消一下

const signed N = 1e6 + 3;
int n, m; char a[N];

#define mid ((l+r)>>1)
#define lson u<<1
#define rson u<<1|1
#define ls lson,l,mid
#define rs rson,mid+1,r
int L[N<<2], R[N<<2];
void build(int u, int l, int r) {
    if(l == r) return void(a[l] == '(' ? L[u] = 1 : R[u] = 1);
    build(ls), build(rs);
    L[u] = L[lson] + L[rson] - min(L[lson], R[rson]); //pushup
    R[u] = R[lson] + R[rson] - min(L[lson], R[rson]);
}
PII ask(int u, int l, int r, int x, int y) { //[x,y]中失配括號數
    if(r < x || l > y) return {0,0}; //沒交集
    if(l >= x && r <= y) return {L[u], R[u]}; //包含關係
    auto [tll, tlr] = ask(ls, x, y);
    auto [trl, trr] = ask(rs, x, y); //得合併一下
    return {tll + trl - min(tll,trr), tlr + trr - min(tll,trr)};
}

signed main() {
    iofast;
    cin >> a + 1 >> m; n = strlen(a + 1);
    build(1, 1, n);
    while(m--) {
        int x, y; cin >> x >> y;
        auto [tL, tR] = ask(1, 1, n, x, y);
        cout << y - x + 1 - tL - tR << endl;
    }
}