每次询问一个区间都根据最开始的线段树在询问的区间重建一棵线段树
view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define PII pair<int, int > using namespace std; typedef long long LL; const int N = 200010; int _, n, Q; char str[N]; PII sum[N << 2], tmp[N << 2]; PII pushUp(PII &l, PII &r) { PII ans = make_pair(l.first, r.second); int mi = min(l.second, r.first); ans.first += r.first - mi; ans.second += l.second - mi; return ans; } void build(int l, int r, int rt) { if(l == r) { sum[rt] = make_pair(str[l] == ')', str[l] == '('); return ; } int m = (l + r) >> 1; build(lson); build(rson); sum[rt] = pushUp(sum[rt << 1], sum[rt << 1 | 1]); } void update(int p, int l, int r, int rt) { if(l == r) { sum[rt].first ^= 1; sum[rt].second ^= 1; return ; } int m = (l + r) >> 1; if(p <= m) update(p, lson); else update(p, rson); sum[rt] = pushUp(sum[rt << 1], sum[rt << 1 | 1]); } void query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { tmp[rt] = sum[rt]; return ; } int m = (l + r) >> 1; tmp[rt << 1] = tmp[rt << 1 | 1] = make_pair(0, 0); if(L <= m) query(L, R, lson); if(R > m) query(L, R, rson); tmp[rt] = pushUp(tmp[rt << 1], tmp[rt << 1 | 1]); } int query2(int L, int R, int k, int l, int r, int rt) { if(tmp[rt].first + tmp[rt].second < k) return -1; if(l == r) return l; int m = (l + r) >> 1; if(R <= m) return query2(L, R, k, lson); if(L > m) return query2(L, R, k, rson); if(L <= l && R >= m) tmp[rt << 1] = sum[rt << 1]; if(L <= m + 1 && R >= r) tmp[rt << 1 | 1] = sum[rt << 1 | 1]; int num = tmp[rt << 1].first; if(tmp[rt << 1].second > tmp[rt << 1 | 1].first) { num += tmp[rt << 1].second - tmp[rt << 1 | 1].first; } if(k <= num) return query2(L, R, k, lson); int now = k - num; now += min(tmp[rt << 1 | 1].first, tmp[rt << 1].second); return query2(L, R, now, rson); } void solve() { scanf("%d%d%s", &n, &Q, str + 1); build(1, n, 1); int a, b, c, d; while(Q--) { scanf("%d", &a); if(a == 1) { scanf("%d", &b); update(b, 1, n, 1); } else { scanf("%d%d%d", &b, &c, &d); query(b, c, 1, n, 1); int ans = query2(b, c, d, 1, n, 1); printf("%d ", ans); } } } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL cin >> _; while(_--) solve(); return 0; }