题目描述

在“无限神机”的核心上,有一个奇怪的括号密码,密码初始已经有一个括号序列,有$n$个限制条件,每个限制条件描述为$l_i$和$r_i$,表示区间$[l_i,r_i]$的括号序列必须合法。调整密码只有一种方式:交换括号序列的任意两个字符。求使得密码满足所有条件最少的交换次数。
括号序列合法定义为:
  $1.$空串$""$是一个合法的括号序列
  $2.$如果$"X"$和$"Y"$是合法的括号序列,则$"XY"$(连接$X$和$Y$)是合法的括号序列
  $3.$如果$"X"$是合法的括号序列,则$"(X)"$是合法的括号序列
  $4.$每个合法的括号序列均可由上述规则推导出。
  例如,$"","()","()()()","(()())"$和$"(((())))"$都是合法的括号序列。显然,只有长度为偶数的才有可能是合法的括号序列


输入格式

第一行有一个字符串$s$,表示原括号序列
第二行一个整数$n$,表示限制条件的个数
第三行$n$个整数,表示$l_i$
第四行$n$个整数,表示$r_i$


输出格式

输出一个整数,表示最少交换次数,无解输出$-1$


样例

样例输入1:

)(
4
0 0 0 0
1 1 1 1

样例输出1:

1

样例输入2:

(((())
2
0 2
1 3

样例输出2:

2


数据范围与提示

样例$1$解释:

$L$和$R$描述了$4$个相同的条件,即要求从$s[0]$到$s[1]$是正确的括号序列。只需要做$1$次交换$s[0]$和$s[1]$就可以得到正确的括号序列。

样例$2$解释:

需要交换$(s[1],s[4])$和交换$(s[3],s[5])$

数据范围:

每个测试点的数据规模及特点如下表所示。设字符串长度为$|S|$


题解

先来考虑区间不重叠的情况:

对每个区间,统计区间前缀和,设前缀和最小值为$w$,区间总和为$a$($a$必须为偶数,否则无解) 使$a$变为$0$,需要从区间外引进括号,只计算引进’)‘数量,最后判断如果所有条件区间的’)‘不够,再从外面进口’)’ 若$a>0$,则需引进$\frac{a}{2}$个’)’,使得$a$变为$0$,每次贪心选择最右边的’(‘修改,$w$不改变(将这些进口操作记录到答案) 若$a<0$,需将这里的’)’出口到其它区间,贪心选择最左边的’)’修改,$w$会增加$|a|$(但这些修改不计算入答案,我们只计算引入’(‘数量) 最后加上$\frac{w}{2}$次区间内部操作,使得前缀和不存在负数。

再来考虑会出现重叠,但是无嵌套:

不妨设这两个区间分别为$l_i\sim r_i$和$l_j\sim r_j$,且$l_j<r_i$。

有一个很简单的解决方法,可以直接将这两个区间拆成$l_i\sim l_j-1,l_j\sim r_i,r_i+1\sim r_j$即可。

如果区间有嵌套仍可以按这种方法解决,代码实现细节比较多。

时间复杂度:$\Theta(n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int l,r;}e[100001];
int n;
int cnt=1,suml,sumr,resl,resr;
char ch[100001];
int l[100001],r[100001];
vector<int> vec[100001];
vector<char> s[100001];
map<vector<int>,int>mp;
int ans;
void work(int x)
{
ans+=(min(l[x],r[x])+1)>>1;
int mid=(l[x]-r[x])>>1;
if(mid<0)
{
mid=-mid;
int flag=min(mid,resl);
mid-=flag;
resl-=flag;
ans+=flag;
resr+=mid;
}
else
{
int flag=min(mid,resr);
mid-=flag;
resr-=flag;
ans+=flag;
resl+=mid;
}
}
int main()
{
scanf("%s%d",ch+1,&n);
int len=strlen(ch+1);
for(int i=1;i<=n;i++){scanf("%d",&e[i].l);e[i].l++;}
for(int i=1;i<=n;i++)
{
scanf("%d",&e[i].r);
e[i].r++;
for(int j=e[i].l;j<=e[i].r;j++)vec[j].push_back(i);
}
mp[vec[0]]=1;
for(int i=1;i<=len;i++)
{
if(!mp[vec[i]])mp[vec[i]]=++cnt;
s[mp[vec[i]]].push_back(ch[i]);
}
for(int i=0;i<s[1].size();i++)
if(s[1][i]=='(')suml++;
else sumr++;
for(int i=2,L,R;i<=cnt;i++)
{
L=R=0;
for(int j=0;j<s[i].size();j++)
{
if(s[i][j]=='(')L++;
else R++;
l[i]=max(l[i],R-L);
}
L=R=0;
for(int j=s[i].size()-1;j>=0;j--)
{
if(s[i][j]=='(')L++;
else R++;
r[i]=max(r[i],L-R);
}
if(abs(L-R)&1){puts("-1");return 0;}
}
for(int i=2;i<=cnt;i++)work(i);
int flag=min(resl,resr);
ans+=flag;
resl-=flag;
resr-=flag;
if(suml<resl||sumr<resr){puts("-1");return 0;}
ans+=resl+resr;
printf("%d",ans);
return 0;
}

rp++

[CSP-S模拟测试]:括号密码(贪心)的更多相关文章

  1. [CSP-S模拟测试]:Blue(贪心)

    题目描述 $Blue$是个动物学家,不仅喜欢研究猫和老鼠,还喜欢研究青蛙.他最近开始研究青蛙过河的问题,可以简化成:数轴上$0$为岸边,$L$为河对岸.$(0,L)$中间存在$n$个石子.已知青蛙一跳 ...

  2. [CSP-S模拟测试]:爬(贪心)

    题目传送门(内部题134) 输入格式 第一行两个数$N,L$. 接下来$N$行每行两个数$A_i,B_i$. 接下来$N$行每行一个整数$C_i$. 输出格式 一行一个整数表示答案,无解输出$-1$. ...

  3. [CSP-S模拟测试]:午餐(贪心+最短路)

    题目传送门(内部题115) 输入格式 第一行两个正整数$n,m$. 接下来$m$行,每行$4$个正整数$u_j,v_j,L_j,R_j$. 接下来一行$n$个数,若第$i$个数为$1$,则$i$号同学 ...

  4. [CSP-S模拟测试]:格式化(贪心)

    题目传送门(内部题105) 输入格式 每组数据第一行一个正整数$n$,表示硬盘块数,接下来$n$行,每行两个正整数,第一个正整数为硬盘格式化前的容量,第二个正整数为格式化之后的容量. 输出格式 对每组 ...

  5. [CSP-S模拟测试]:优化(贪心+DP)

    题目描述 $visit\text{_}world$发现有下优化问题可以用很平凡的技巧解决,所以他给你分享了这样一道题:现在有长度为$N$的整数序列$\{ a_i\}$,你需要从中选出$K$个不想叫的连 ...

  6. [CSP-S模拟测试]:表达式密码(模拟)

    题目传送门(内部题87) 输入格式 从文件$expression.in$中读入数据.输入一行,一个字符串$S$,表示原表达式,保证为合法表达式 输出格式 输出到文件$expression.out$中. ...

  7. [CSP-S模拟测试]:梦境(贪心+小根堆)

    题目描述 智者奥尔曼曾说过:有缘的人即使相隔海角天涯,也会在梦境中相遇. $IcePrince\text{_}1968$和$IcePrincess\text{_}1968$便是如此.有一天$IcePr ...

  8. [CSP-S模拟测试]:d(贪心+树状数组)

    题目传送门(内部题65) 输入格式 第一行,一个自然数$T$,代表数据组数.对于每组数据:第一行,一个正整数$n$,一个自然数$m$.接下来$n$行,每行两个正整数,$a_i,b_i$. 输出格式 对 ...

  9. [CSP-S模拟测试]:Tree(贪心)

    题目描述 给定一颗$n$个点的树,树边带权,试求一个排列$P$,使下式的值最大 $$\sum \limits_{i=1}^{n-1}maxflow(P_i,P_{i+1})$$ 其中$maxflow( ...

随机推荐

  1. Django之AJAX传输JSON数据

    目录 Django之AJAX传输JSON数据 AJAX 中 JSON 数据传输: django响应JSON类型数据: django 响应 JSON 类型数据: Django之AJAX传输JSON数据 ...

  2. 02、CDF文件

    有了探针排布图像的基础,我们就可以更好地理解CDF文件了.假如每个探针的位置用一个坐标表示,以左上角为(0,0),那么整张芯片的坐标就如下图(行数n必须等于列数m,这里共有n*m个探针): 0,0 1 ...

  3. sql认识

    DDL – Data Definition Language数据定义语言DML – Data Manipulation Language数据操作语言DCL – Data Control Languag ...

  4. wpf prism加载独立模块实例

    一.首先看看文件的组织架构 module1 module2生成dll某块.Shell来显示管理模块 二,看看关键bootstrapper类 using System;using System.Coll ...

  5. 普通交叉验证(OCV)和广义交叉验证(GCV)

    普通交叉验证OCV OCV是由Allen(1974)在回归背景下提出的,之后Wahba和Wold(1975)在讨论 了确定多项式回归中多项式次数的背景,在光滑样条背景下提出OCV. Craven和Wa ...

  6. git常用命令之log

       查看提交日志记录 基础命令:  git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon < ...

  7. openlayers之框选放缩DragZoom(vue项目)

    环境vue3.0项目 最初是以npm i ol -s方式安装的ol,import方式导入引用,但是实际使用的时候一直报ol is not defined,最后选择在HTML以script标签引入ol, ...

  8. Electron 5.0 发布

    Electron 5.0的主要变化 打包应用程序现在的行为与默认应用程序相同.将创建一个默认的应用程序菜单(除非应用程序有一个),并且将自动处理全部关闭窗口的事件. (除非应用程序处理事件) 现在默认 ...

  9. Docker之rm: Device or resource busy

    docker 容器里 rm -rf /data 提示: rm: cannot remove ‘/data’: Device or resource busy 原因: 在建立容器的时候做了相应目录的挂载 ...

  10. cacti监控

    cacti监控 cacti简介 Cacti是一套基于php,mysql,snmp及rrdtool开发的网络流量监测图形分析工具.它通过snmpget获取数据,使用rrdtool绘画图形 Cacti轮询 ...