Almost Regular Bracket Sequence

CodeForces - 1095E

You are given a bracket sequence ss consisting of nn opening '(' and closing ')' brackets.

A regular bracket sequence is a bracket sequence that can be transformed into a correct arithmetic expression by inserting characters '1' and '+' between the original characters of the sequence. For example, bracket sequences "()()", "(())" are regular (the resulting expressions are: "(1)+(1)", "((1+1)+1)"), and ")(" and "(" are not.

You can change the type of some bracket sisi. It means that if si=si= ')' then you can change it to '(' and vice versa.

Your task is to calculate the number of positions ii such that if you change the type of the ii-th bracket, then the resulting bracket sequence becomes regular.

Input

The first line of the input contains one integer nn (1≤n≤1061≤n≤106) — the length of the bracket sequence.

The second line of the input contains the string ss consisting of nn opening '(' and closing ')' brackets.

Output

Print one integer — the number of positions ii such that if you change the type of the ii-th bracket, then the resulting bracket sequence becomes regular.

Examples

Input

6
(((())

Output

3

Input

6
()()()

Output

0

Input

1
)

Output

0

Input

8
)))(((((

Output

0

翻译:

赵老师实在是太强了,以至于他随便出的题就难倒了张老师

他给了张老师一个括号序列S,其中只包含"("和")"

他只允许张老师更改一个位置上的符号类型,如把"("变为")",从而使得整个括号序列是一个合法的括号序列

请你帮张老师计算一下有几个位置,更改了这个位置的括号类型,整个括号序列将变成合法的括号序列

思路:

https://www.cnblogs.com/qieqiemin/p/11491557.html

我这篇博客的题目是用线段树维护括号序列的最大合法匹配的子序列长度。(只有区间询问)

如果不会建议前去学习。

那么对于本题,

我们可以增加一个单点更新的功能,然后对于1到n每一个字符,单点更新为相反的字符串。

然后区间查询整个(即1~n)字符串的最大合法匹配的子序列长度是否为n,如果是就证明当前字符串是整体完美匹配的。答案+=1即可,然后将其再返过来更新,恢复成原始的字符串。再移步到下一个位置。统计最终答案即可。

还有一种是分析性质和规律的做法,推荐这篇博客:https://blog.csdn.net/tianyizhicheng/article/details/86776263

贴上我的ac代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
int l, r;
int num;
int a;// (
int b;// )
} segmeng_tree[maxn << 2];
char s[maxn];
int n;
int m;
void pushup(int rt)
{
int x = min(segmeng_tree[rt << 1].a, segmeng_tree[rt << 1 | 1].b);
segmeng_tree[rt].num = x + segmeng_tree[rt << 1].num + segmeng_tree[rt << 1 | 1].num;
segmeng_tree[rt].a = segmeng_tree[rt << 1].a + segmeng_tree[rt << 1 | 1].a - x;
segmeng_tree[rt].b = segmeng_tree[rt << 1].b + segmeng_tree[rt << 1 | 1].b - x;
}
void build(int rt, int l, int r)
{
segmeng_tree[rt].l = l;
segmeng_tree[rt].r = r;
if (l == r) {
segmeng_tree[rt].a = s[l] == '(';
segmeng_tree[rt].b = s[l] == ')';
segmeng_tree[rt].num = 0;
} else {
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushup(rt);
}
} node ask(int rt, int l, int r)
{
if (segmeng_tree[rt].l >= l && segmeng_tree[rt].r <= r) {
return segmeng_tree[rt];
}
int mid = (segmeng_tree[rt].l + segmeng_tree[rt].r) >> 1;
if (r <= mid) {
return ask(rt << 1, l, r);
} else if (l > mid) {
return ask(rt << 1 | 1, l, r);
} else {
node res1 = ask(rt << 1, l, r);
node res2 = ask(rt << 1 | 1, l, r);
node res = res1;
int x = min(res1.a, res2.b);
res.num += x;
res.b += res2.b;
res.a += res2.a;
res.num += res2.num;
res.b -= x;
res.a -= x;
return res;
}
}
void update(int rt, int x, int val)
{
if (segmeng_tree[rt].l == segmeng_tree[rt].r && segmeng_tree[rt].l == x)
{
if (val)
{
segmeng_tree[rt].a = 1;
segmeng_tree[rt].b = 0;
} else
{
segmeng_tree[rt].a = 0;
segmeng_tree[rt].b = 1;
}
} else
{
int mid = (segmeng_tree[rt].r + segmeng_tree[rt].l) >> 1;
if (x <= mid)
{
update(rt << 1, x, val);
} else
{
update(rt << 1 | 1, x, val);
}
pushup(rt);
}
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
scanf("%d",&n);
scanf("%s", s + 1);
// n = strlen(s + 1);
build(1, 1, n);
int ans = 0;
repd(i, 1, n)
{
if (s[i] == '(')
{
update(1,i,0);
int len=ask(1,1,n).num*2;
if(len==n)
{
ans++;
}
update(1,i,1);
}else
{
update(1,i,1);
int len=ask(1,1,n).num*2;
if(len==n)
{
ans++;
}
update(1,i,0);
}
}
printf("%d\n",ans );
return 0;
} inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}

Almost Regular Bracket Sequence CodeForces - 1095E (线段树,单点更新,区间查询维护括号序列)的更多相关文章

  1. HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)

    HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...

  2. NYOJ-568/1012//UVA-12299RMQ with Shifts,线段树单点更新+区间查询

    RMQ with Shifts 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 ->  Link1  <- -> Link2  <- 以上两题题意是一样 ...

  3. HDU 1166敌兵布阵+NOJv2 1025: Hkhv love spent money(线段树单点更新区间查询)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  4. HDU1166(线段树单点更新区间查询)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  5. HDU 1754.I Hate It-结构体版线段树(单点更新+区间查询最值)

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  6. CDOJ 1073 线段树 单点更新+区间查询 水题

    H - 秋实大哥与线段树 Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%lld & %llu Submit S ...

  7. Who Gets the Most Candies? POJ - 2886(线段树单点更新+区间查询+反素数)

    预备知识:反素数解析 思路:有了反素数的解法之后就是线段树的事了. 我们可以用线段树来维护哪些人被淘汰,哪些人没被淘汰,被淘汰的人的位置,没被淘汰的人的位置. 我们可以把所有人表示为一个[1,n]的区 ...

  8. NBUT 1602 Mod Three(线段树单点更新区间查询)

    [1602] Mod Three 时间限制: 5000 ms 内存限制: 65535 K 问题描述 Please help me to solve this problem, if so, Liang ...

  9. hdoj 1541 Stars【线段树单点更新+最大值维护】

    Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

随机推荐

  1. 基于Opencv的梯度及其方向

    我们都知道梯度很好求,只需要将[-1,1] 与图像分别在x 方向和y方向卷积,即可求得两个方向上的梯度.不过在求梯度方向时,还是有些麻烦,因为梯度方向会指向360°的任何一个方向,所以直接用atan( ...

  2. python urllib2 实现大文件下载

    使用urllib2下载并分块copy: # from urllib2 import urlopen # Python 2 from urllib.request import urlopen # Py ...

  3. CentOS7之yum仓库配置

    操作系统版本:CentOS Linux release 7.2.1511 (Core)  Yum软件版本:yum-3.4.3-132.el7.centos.0.1.noarch  Yum主配置文件:/ ...

  4. 使用Minikube运行一个本地单节点Kubernetes集群(阿里云)

    使用Minikube运行一个本地单节点Kubernetes集群中使用谷歌官方镜像由于某些原因导致镜像拉取失败以及很多人并没有代理无法开展相关实验. 因此本文使用阿里云提供的修改版Minikube创建一 ...

  5. spring事务使用

    spring的事务管理有几种方式实现,如何实现? 事务的实现方式:实现方式共有两种:编码方式:声明式事务管理方式 基于AOP技术实现的声明式事务管理,实质就是:在方法执行前后进行拦截,然后再目标方法开 ...

  6. Netty对常用编解码的支持

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! Netty对编解码的支持 打开Netty的源码,它对很多的编码器都提 ...

  7. linux系统设置允许密码登录

    编辑  /etc/ssh/sshd_config 文件 将PasswordAuthentication 的值改为 yes 然后重启ssh 服务 进入到  /etc/init.d 文件夹内 执行 ./s ...

  8. redis 工具包

    java通过jedis操作redis(从JedisPool到JedisCluster) redis作为一个缓存数据库,在绝大多数java项目开发中是必须使用的,在web项目中,直接配合spring-r ...

  9. C#面向对象11 里氏转换

    里氏转换 1.子类可以赋值给父类. using System; using System.Collections.Generic; using System.Linq; using System.Te ...

  10. SQLite数据库_c/s架构的心得

    1.使用是Navicat Premium软件, Microsoft Windows版本. 2.选择SQLite并新建数据库: 3.将建好的SQLite数据库,放到新建的项目的debug文件下中, 并在 ...