Codeforces Round #603 (Div. 2) E - Editor(线段树,括号序列)
🦋 🦋 🦋
不知不觉已经咕了。。七八十来场CF了,,为什么一到考试周比赛这么多啊,雷菊苣上蓝了(在我咕掉的其中一场。。羡慕)
自己已经这么菜了இ௰இ,考完试要抓紧时间了
题意:一串操作序列,问你每个操作之后是否是合法括号,以及括号的最大嵌套深度;
学到了处理括号序列合法性的新方法:
1.将左括号视为1,右括号视为-1
2.前缀和需要满足任意前缀和大于等于0
3.整个序列和等于0
4.此时嵌套最大深度即为前缀和最大值
然后就是更新的时候判断一下这里以前是什么符号,线段树维护一下前缀和最大最小值,用一个sum记录下总和
#define lson o << 1
#define rson o << 1 | 1
#define mid (l + r) / 2
struct Tree
{
int add,minv,maxv;
} tree[MAXN<<2];
int n, m;
char s[MAXN], res[MAXN];
void pushup(int o)
{
tree[o].maxv = max(tree[lson].maxv, tree[rson].maxv);
tree[o].minv = min(tree[lson].minv, tree[rson].minv);
}
void pushdown(int o)
{
if (tree[o].add)
{
tree[lson].add += tree[o].add,tree[rson].add += tree[o].add;
tree[lson].maxv += tree[o].add,tree[rson].maxv += tree[o].add;
tree[lson].minv += tree[o].add,tree[rson].minv += tree[o].add;
tree[o].add = 0;
}
}
void add(int o, int l, int r, int from, int to, int v)//区间修改
{
if (l >= from && r <= to)
{
tree[o].add += v, tree[o].maxv += v,tree[o].minv += v;
return;
}
pushdown(o);
if (from <= mid) add(lson, l, mid, from, to, v);
if (to > mid) add(rson, mid + 1, r, from, to, v);
pushup(o);
}
int ask(int o, int l, int r, int p)//单点查询
{
if (l == r) return tree[o].maxv;
pushdown(o);
if (p <= mid) return ask(lson, l, mid, p);
else return ask(rson, mid + 1, r, p);
}
int main()
{
scanf("%d", &n);
scanf("%s", s + 1);
int now = 1;
for (int i = 1; i <= n; i++)
{
if (s[i] == 'L') now--;
else if (s[i] == 'R') now++;
else if (s[i] == '(')
{
if (res[now] == ')') add(1, 1, n, now, n, 2);
else if (res[now] != '(') add(1, 1, n, now, n, 1);
res[now] = '(';
}
else if (s[i] == ')')
{
if (res[now] == '(') add(1, 1, n, now, n, -2);
else if (res[now] != ')') add(1, 1, n, now, n, -1);
res[now] = ')';
}
else
{
if (res[now] == '(') add(1, 1, n, now, n, -1);
else if (res[now] == ')') add(1, 1, n, now, n, 1);
res[now] = s[i];
}
now = max(now, 1);
if (tree[1].minv >= 0 && ask(1, 1, n, n) == 0) printf("%d ", tree[1].maxv);
else printf("-1 ");
}
printf("\n");
return 0;
}

浙公网安备 33010602011771号