【csu oj 1542】线段树

题目大意:给定一个合法的括号序列(只包含'(',')'),有q次操作,对每次操作改变一个位置的括号,求最左端的位置,使得改变这个位置上的括号以后,新序列合法(完全配对)。

思路:对于合法的括号序列,如果把括号序列一次进行栈操作,把'('进栈,')'则把最近的'('出栈,令a[i]表示到i位置后栈里面的左括号个数,也就是i位置的左括号数目和右括号数目的差。则原序列对应新的数组a。原序列合法 等价于 对于1<=i<=n,a[i]>=0 恒成立。那么对于把位置pos上的括号改变一下,如果是'(' - ')',那么a[pos~n]会都减去2,如果是')'->'(',那么a[pos~n]会都加上2。分类讨论后,答案不难得出。对于'('->')'答案就是从左至右找第一个右括号;对于')'->'(',答案就是找一个最左端的位置pos0,使得a[pos0~pos-1]都大于等于2。对于找第一个右括号,可以转化为用新的数组b[i] = a[i] - i,找第一个小于0的位置,进而转化为找最大的前缀区间使得这个区间上的b的最小值等于0。对于找最左端的位置,也可以转化为区间最值来做,详见代码:

  1 #include <iostream>

  2 #include <cstdio>

  3 #include <algorithm>

  4 #include <cstring>

  5 #include <map>

  6 #include <queue>

  7 #include <cmath>

  8 #include <vector>

  9 #include <ctime>

 10 #define mem0(a) memset(a, 0, sizeof(a))

 11 #define lson l, m, rt << 1

 12 #define rson m + 1, r, rt << 1 | 1

 13 #define define_m int m = (l + r) >> 1

 14 #define LL long long

 15 #define Rep(a, b) for(int a = 0; a < b; a++)

 16 #define lowbit(x) ((x) & (-(x)))

 17 const int dx[4] = {1, 0, -1, 0};

 18 const int dy[4] = {0, -1, 0, 1};

 19 const int INF = 1e9 + 7;

 20 const int maxn = 300010;

 21 const double eps = 1e-13;

 22 typedef double db;

 23 using namespace std;

 24 struct SegTree {

 25     struct Node {

 26         int minv, add;

 27     } tree[maxn << 2];

 28     void PushUp(int rt) {

 29         tree[rt].minv = min(tree[rt << 1].minv, tree[rt << 1 | 1].minv);

 30     }

 31     void PushDown(int rt) {

 32         int add = tree[rt].add;

 33         if (add) {

 34             tree[rt << 1].minv += add;

 35             tree[rt << 1].add += add;

 36             tree[rt << 1 | 1].minv += add;

 37             tree[rt << 1 | 1].add += add;

 38             tree[rt].add = 0;

 39         }

 40     }

 41     void Build(int a[], int l, int r, int rt) {

 42         tree[rt].add = 0;

 43         if (l == r) {

 44             tree[rt].minv = a[l];

 45             return ;

 46         }

 47         define_m;

 48         Build(a, lson);

 49         Build(a, rson);

 50         PushUp(rt);

 51     }

 52     void Update(int L, int R, int x, int l, int r, int rt) {

 53         if (L <= l && r <= R) {

 54             tree[rt].minv += x;

 55             tree[rt].add += x;

 56             return;

 57         }

 58         define_m;

 59         PushDown(rt);

 60         if (L <= m) Update(L, R, x, lson);

 61         if (R > m) Update(L, R, x, rson);

 62         PushUp(rt);

 63     }

 64     int Query1(int l, int r, int rt) {

 65         if (l == r) return tree[rt].minv == 0;

 66         define_m;

 67         PushDown(rt);

 68         if (tree[rt << 1].minv < 0)  return Query1(lson);

 69         int len = r - l + 1;

 70         return len - (len >> 1) + Query1(rson);

 71     }

 72     int Query2(int l, int r, int rt) {

 73         if (l == r) return tree[rt].minv == 0;

 74         define_m;

 75         PushDown(rt);

 76         if (tree[rt << 1 | 1].minv < 2) return Query2(rson);

 77         int len = r - l + 1;

 78         return (len >> 1) + Query2(lson);

 79     }

 80 };

 81 int n, q;

 82 char s[300010];

 83 int a[300010], b[300010], c[300010];

 84 SegTree G, H;

 85 void Init() {

 86     for (int i = 0; i < n; i++) {

 87         c[i + 1] = c[i];

 88         if (s[i] == '(') c[i + 1]++;

 89         else c[i + 1]--;

 90     }

 91     for (int i = 1; i <= n; i++) {

 92         a[i] = c[i] - i;

 93         b[i] = c[i];

 94     }

 95 }

 96 int main() {

 97     //freopen("in.txt", "r", stdin);

 98     cin >> n >> q;

 99     scanf("%s", s);

100     Init();

101     G.Build(a, 1, n, 1);

102     H.Build(b, 1, n, 1);

103     for (int i = 0; i < q; i++) {

104         int pos, tmp;

105         scanf("%d", &pos);

106         if (s[pos - 1] == '(') {

107             s[pos - 1] = ')';

108             G.Update(pos, n, -2, 1, n, 1);

109             H.Update(pos, n, -2, 1, n, 1);

110             printf("%d\n", tmp = G.Query1(1, n, 1) + 1);

111             G.Update(tmp, n, 2, 1, n, 1);

112             H.Update(tmp, n, 2, 1, n, 1);

113             s[tmp - 1] = '(';

114         }

115         else {

116             s[pos - 1] = '(';

117             H.Update(pos, n, 2, 1, n, 1);

118             G.Update(pos, n, 2, 1, n, 1);

119             printf("%d\n", tmp = n - H.Query2(1, n, 1) + 1);

120             H.Update(tmp, n, -2, 1, n, 1);

121             G.Update(tmp, n, -2, 1, n, 1);

122             s[tmp - 1] = ')';

123         }

124     }

125     return 0;

126 }
View Code

 

你可能感兴趣的:(线段树)