UVALive 6838 (括號匹配x線段樹)
阿新 • • 發佈:2019-01-30
題意:
。。
題目地址
思路:
定義a, b陣列, indexed from 1
a[i] = a[i-1] + ( s[i] == '(' ? 1 : -1 );
定義一個b陣列
b[i] = a[i] - i
s平衡的必要條件是,a[n] = 0。雖然僅靠這個是不可靠的。。但用這個必要條件已經可以ac了。。
如果b[i] < 0,則 [1, i] 中一定有右括號
1)修改a[x]為 ),[x,n]區間減2
為使a[n] = 0, 找第一個右括號改為左括號
2)修改a[x]為(,[x, n] 區間加2
這時,需要找最左邊的左括號,使得從它開始的a值全部不小於2。
因為修改後a出現負數是不行的。。
const int N = 300005;
const int INF = INT_MAX;
char str[N];
int a[N];
struct Node {
int x, y, add; // a[i], a[i] - i, lazy
inline void upd(int delta) {
x += delta; y += delta; add += delta;
}
};
Node tr[N<<2];
int qL, qR;
#define lc o<<1
#define rc o<<1|1
void push_down(int o) {
if ( tr[o].add ) {
tr[lc].upd(tr[o].add);
tr[rc].upd(tr[o].add);
tr[o].add = 0;
}
}
void push_up(int o) {
tr[o].x = min ( tr[lc].x, tr[rc].x );
tr[o].y = min ( tr[lc].y, tr[rc].y );
tr[o].add = 0;
}
void modify(int o, int l, int r, int v) {
if ( qL <= l && r <= qR ) {
tr [o].upd(v); return;
}
push_down(o);
int m = (l + r) >> 1;
if ( qL <= m )
modify(lc, l, m, v);
if ( qR > m )
modify(rc, m+1, r, v);
push_up(o);
}
int query_1(int o, int l, int r) {
if ( l == r ) return l;
int m = (l + r) >> 1, res;
push_down(o);
if ( tr[lc].y < 0 ) {
res = query_1(lc, l, m);
} else {
res = query_1(rc, m+1, r);
}
push_up(o);
return res;
}
int q2_res;
void query_2(int o, int l, int r) {
if ( tr[o].x >= 2 ) {
q2_res = l; return;
}
if ( l == r ) return;
push_down(o);
int m = (l + r) >> 1;
if ( tr[rc].x >= 2 ) {
q2_res = m + 1;
query_2(lc, l, m);
} else {
query_2(rc, m+1, r);
}
push_up(o);
}
void build(int o, int l, int r) {
if ( l == r ) {
tr[o] = (Node) { a[l], a[l] - l, 0 };
} else {
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m+1, r);
push_up(o);
}
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
int n, q;
scanf("%d%d", &n, &q);
scanf("%s", str+1);
a[1] = 1;
rep(i, 2, n) {
if ( str[i] == '(' )
a[i] = a[i-1] + 1;
else
a[i] = a[i-1] - 1;
}
build(1, 1, n);
rep(o, 1, q) {
int x, tmp;
scanf("%d", &x);
if ( str[x] == '(' ) {
str[x] = ')';
qL = x, qR = n;
modify(1, 1, n, -2);
tmp = query_1(1, 1, n);
str[tmp] = '(';
qL = tmp, qR = n;
modify(1, 1, n, 2);
} else {
str[x] = '(';
qL = x, qR = n;
modify(1, 1, n, 2);
query_2(1, 1, n);
str[q2_res] = ')';
qL = q2_res, qR = n;
modify(1, 1, n, -2);
tmp = q2_res;
}
printf("%d\n", tmp);
}
return 0;
}