题目大意:
给出括号序列然后两种操作:
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;
}