【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

 

转载于:https://www.cnblogs.com/jklongint/p/4361522.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值