题目大意:
给出括号序列然后两种操作:
1.修改某个括号为另外一种
2.询问在区间[L, R]中的括号在忽略掉匹配好的括号之后第K个括号的位置, 即没有匹配的括号中第K个的位置
大致思路:
首先可以对于括号序列建立线段树, 线段树每个节点表示当前区间[L, R]中没有匹配的')'数量和'('数量, 这个是可以满足区间合并的
那么对于每次询问当没匹配的')'和‘(‘总数不够K时就是-1, 否则的话分治一下, 对于是‘)'的情况从左往右看, 对于是'('的情况从右往左看, 考虑第K个没匹配的括号在[L, R]二分之后的左边区间还是右边区间, 注意在递归向下的时候K会发生的变化即可, 建立线段树O(n), 每次修改复杂度O(logn), 每次询问复杂度O((logn)^2)
代码如下:
交了G++才过....布吉岛是不是因为有更好的解法...还是因为代码写搓了...
加了整数的读入优化的...
Result : Accepted Memory : 5912 KB Time : 7113 ms
/* * Author: Gatevin * Created Time: 2015/9/10 16:28:29 * File Name: Sakura_Chiyo.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; #define maxn 200010 char in[maxn]; int n, Q; inline int Max(int x, int y) { if(x > y) return x; return y; } struct Segment_Tree { #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 struct State { int l, r; State(int _l, int _r) { l = _l, r = _r; } State(){}; }; State s[maxn << 2]; void pushUp(int rt) { s[rt] = State(s[rt << 1].l + Max(0, s[rt << 1 | 1].l - s[rt << 1].r), s[rt << 1 | 1].r + Max(0, s[rt << 1].r - s[rt << 1 | 1].l)); }; void build(int l, int r, int rt) { if(l == r) { if(in[l] == ')') s[rt] = State(1, 0); else s[rt] = State(0, 1); return; } int mid = (l + r) >> 1; build(lson); build(rson); pushUp(rt); } void update(int l, int r, int rt, int pos) { if(l == r) { if(in[l] == '(') in[l] = ')'; else in[l] = '('; if(in[l] == '(') s[rt] = State(0, 1); else s[rt] = State(1, 0); return; } int mid = (l + r) >> 1; if(pos <= mid) update(lson, pos); else update(rson, pos); pushUp(rt); } State query(int l, int r, int rt, int L, int R) { if(l >= L && r <= R) return s[rt]; int mid = (l + r) >> 1; State sl, sr; bool fl = 0, fr = 0; if(mid >= L) sl = query(lson, L, R), fl = 1; if(mid + 1 <= R) sr = query(rson, L, R), fr = 1; if(!fl) return sr; if(!fr) return sl; return State(sl.l + Max(0, sr.l - sl.r), sr.r + Max(0, sl.r - sr.l)); } int find(int L, int R, int K, char c) { if(L == R) return L; int mid = (L + R) >> 1; if(c == ')') { State sl = query(1, n, 1, L, mid); if(sl.l >= K) return find(L, mid, K, c); else return find(mid + 1, R, K - sl.l + sl.r, c); } else { State sr = query(1, n, 1, mid + 1, R); if(sr.r >= K) return find(mid + 1, R, K, c); else return find(L, mid, K - sr.r + sr.l, c); } } void solve(int L, int R, int K) { State ret = query(1, n, 1, L, R); if(ret.l + ret.r < K) { printf("-1\n"); return; } if(ret.l >= K)//说明这个括号是')' printf("%d\n", find(L, R, K, ')'));//[L, R]中从左往右第K个')' else printf("%d\n", find(L, R, ret.l + ret.r - K + 1, '('));//说明这个括号是从右往左第 ret.l + ret.r - K + 1个'(' } }; Segment_Tree st; void Get(int &x) { x = 0; char c; while(1) { c = getchar(); if(c >= '0' && c <= '9') x = x*10 + c - '0'; else break; } } int main() { int T; //scanf("%d", &T); Get(T); while(T--) { //scanf("%d %d", &n, &Q); Get(n); Get(Q); gets(in + 1); st.build(1, n, 1); while(Q--) { int op; //scanf("%d", &op); Get(op); if(op == 1) { int pos; //scanf("%d", &pos); Get(pos); st.update(1, n, 1, pos); } else { int L, R, K; //scanf("%d %d %d", &L, &R, &K); Get(L); Get(R); Get(K); st.solve(L, R, K); } } } return 0; }