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;
}
}

浙公网安备 33010602011771号