1. 程式人生 > >UVALive 6838 (括號匹配x線段樹)

UVALive 6838 (括號匹配x線段樹)

題意:
。。
題目地址
思路:
定義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; }