【codeforces 1095E - Almost Regular Bracket Sequence】【线段树】【前缀和】【括号匹配】

https://codeforces.com/problemset/problem/1095/E

【题意】

问有多少的个位置,更换一个括号,就能使括号匹配

【思路】

线段树维护。

遍历每一个位置,单点修改。建一棵线段树,树上节点维护两个信息:左括号数,右括号数

区间合并:

假设左儿子为:))(((,右儿子为:))(((,合并消除()之后就变成了))((((

所以我可以从1枚举到n,在线段树中改变第 i 个位置的括号,如果线段树根节点的tl=tr=0,那么答案就++。

暴力修改,线段树维护

 

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
char s[maxn];
int tl[maxn * 4], tr[maxn * 4];

void push(int p, int ls, int rs)
{
	if (tr[ls] >= tl[rs])
	{
		tl[p] = tl[ls];
		tr[p] = tr[rs] + tr[ls] - tl[rs];
	}
	else
	{
		tr[p] = tr[rs];
		tl[p] = tl[ls] + tl[rs] - tr[ls];
	}
}

void build(int p, int l, int r)
{
	if (l == r)
	{
		if (s[l] == '(')
			tr[p] = 1;
		else tl[p] = 1;
		return;
	}
	int m = (l + r) / 2, ls = p * 2, rs = p * 2 + 1;
	build(ls, l, m);
	build(rs, m + 1, r);
	push(p, ls, rs);
}

void up(int p, int l, int r, int k)
{
	if (l == r)
	{
		tl[p] = !tl[p];
		tr[p] = !tr[p];
		return;
	}
	int m = (l + r) / 2, ls = p * 2, rs = p * 2 + 1;
	if (k <= m)up(ls, l, m, k);
	else up(rs, m + 1, r, k);
	push(p, ls, rs);
}

int main()
{
	int n;
	while (~scanf("%d", &n)) {
		int  ans = 0;
		scanf("%s", s + 1);
		build(1, 1, n);
		for (int i = 1; i <= n; i++)
		{
			up(1, 1, n, i);
			if (tl[1] == 0 && tr[1] == 0)ans++;
			up(1, 1, n, i);
		}
		cout << ans;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值