「HNSDFZ暑期集训 测试1」「LuoguT36485」 括号(贪心
Description
给定一个由左括号'('和右括号')'组成的字符串s,其中第i个括号的权值为ai。
我们定义一个括号序列t为合法括号序列
,当且仅当满足下列条件之一:
1.t为空串
2.t=(A),其中A为一个合法括号序列
3.t=AB,其中A,B均为合法括号序列
比如(()()),()(())均为合法括号序列,但((), ())(不是合法括号序列。
Input
输入第一行一个整数n,表示s的长度。
第二行一个长度为n,且由括号组成的字符串s。
第三行n个整数,第i个整数ai表示第i个括号的值。
Output
输出仅一行一个整数,表示答案。
Sample Input1
6
())(()
1 2 1 2 1 2
Sample Output1
7
Sample Input2
6
((()))
2 1 -2 1 2 3
Sample Output2
8
Hint
40%的数据n<=20,0<=ai<=100
接下来30%的数据 n<=2000,|ai|<=1e5
接下来30%的数据 n<=2e5,|ai|<=1e3,左括号全都在右括号的左边
题解
官方题解:
分情况讨论
n<=2000时 用dp,F [ i ] [ j ]表示前i个中有j个左括号时的最大值
n >2000时,分别对左括号的值和右括号的值排序(cmp从大到小),用for循环从1走一遍,若a[i]+b[i]>0 ans+=a[i]+b[i],否则return.
但是我的思路可以把n取到1e6并且不需要特殊性质啊!QAQ
我们先假设现在已经从头开始扫了一段括号序列,并且前一段已经标记了最优的序列有哪些括号。对于现在新加进来的括号,我们仍然要试图维持当前选择最优。
如果是左括号,我们不做任何处理(也做不了什么);
如果是右括号,那么不外乎三种情况:
1.不做任何处理;
2.在这个右括号之前找一个未被选的左括号,与其配对(标记此左括号和右括号);
3.在这个右括号之前找一个被选了的右括号,将其替代(清除前面的右括号的标记,并且标记新的右括号)
只要在这三种操作中取一个最优操作,就仍然可以保持当前最优。
那么,用一个for从头至尾循环,复杂度O(n),
对每个当前括号,做以上判断,
其中的往前找要求的括号的操作(2)和操作(3)可以用堆实现,复杂度O(logn)
一共O(nlogn)
代码://考场代码 因为可以水到分所以懒得写堆了(其实可以直接调用priority_queue 也很方便)
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int s[];
int q[];
bool sf[];
int a[];
int b[];
bool cmp(int qaq,int qwq)
{
return qaq>qwq;
}
int main()
{
int n;
cin>>n;
if(n<)
{
for(int i=;i<=n;++i)
{
char x;
cin>>x;
if(x=='(')s[i]=;
else s[i]=;
}
for(int i=;i<=n;++i)
{
cin>>q[i];
//cout<<i<<" "<<s[i]<<" "<<a[i]<<endl;
if(s[i]==)
{
int u=-,pu=;
for(int j=i-;j;--j)
if(s[j]==&&!sf[j])
{
if(q[j]>u){u=q[j];pu=j;}
}
int v=,pv=;
for(int j=i-;j;--j)
if(s[j]==&&sf[j])
{
if(q[j]<v){v=q[j];pv=j;}
}
//cout<<u<<" "<<pu<<" "<<v<<" "<<pv;
if(pu&&pv)
{
if(u+q[i]>=q[i]-v&&u+q[i]>)
{
sf[pu]=;sf[i]=;
}
else if(q[i]-v>u+q[i]&&q[i]-v>)
{
sf[pv]=;sf[i]=;
}
}
else
{
if(pu&&u+q[i]>)
{
sf[pu]=;sf[i]=;
}
else if(pv&&q[i]-v>)
{
sf[pv]=;sf[i]=;
}
}
//cout<<endl;
}
}
int ans=;
for(int i=;i<=n;++i)
if(sf[i]){ans+=q[i];}
cout<<ans;//强大怪!!!
return ;
}
else
{
for(int i=;i<=n;++i)
{
char x;
cin>>x;
if(x=='(')s[i]=;
else s[i]=;
}
int toa=,tob=;
for(int i=;i<=n;++i)
{
int x;
scanf("%d",&x);
if(s[i]==)a[++toa]=x;
else b[++tob]=x;
}
sort(a+,a+toa+,cmp);
sort(b+,b+tob+,cmp);
int ans=;
for(int i=;i<=min(toa,tob);++i)
{
if(a[i]+b[i]>)ans+=(a[i]+b[i]);
else {cout<<ans;return ;}
}
cout<<ans;//强大怪!!!
return ;
}
}
//注释强大怪 你会rp++
UPD
$O(nlogn)$的堆写法↓
/*
qwerta
T36485 括号 Accepted
100
代码 C++,0.7KB
提交时间 2018-11-05 20:42:18
耗时/内存 442ms, 2124KB
*/
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
char ch[];
int v[];
priority_queue<int,vector<int>,greater<int> >r;//r放右括号
priority_queue<int>l;//l放左括号
int main()
{
//freopen("a.in","r",stdin);
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=;i<=n;++i)
cin>>ch[i];
for(int i=;i<=n;++i)
cin>>v[i];
//
int ans=;
for(int i=;i<=n;++i)
{
if(ch[i]=='(')
{
l.push(v[i]);
}
else
{
int x,y;
if(l.empty())x=-;//赋成-1不碍事儿
else x=v[i]+l.top();
if(r.empty())y=-;
else y=v[i]-r.top();
if(x>=y&&x>=)//找个没用过的左括号
{
ans+=x;
l.pop();
r.push(v[i]);
}
else if(y>=x&&y>=)//替代一个用过的右括号
{
ans+=y;
r.pop();
r.push(v[i]);
}
}
}
cout<<ans;
return ;
}
「HNSDFZ暑期集训 测试1」「LuoguT36485」 括号(贪心的更多相关文章
- 「HNSDFZ暑期集训 测试1」「LuoguT36488」 连连看
题目描述 给定一个n × m的矩形地图,每个各自上可能为空,可能有牌,牌上有一个数字. 对于两张同样数字的牌,如果我们可以在地图上用不超过三根水平或竖直,在地图界内,且不经过其他牌的线段将两张牌连起来 ...
- loj #6046. 「雅礼集训 2017 Day8」爷
#6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- 「雅礼集训 2017 Day7」事情的相似度
「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...
- 「雅礼集训 2017 Day2」解题报告
「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...
- 「雅礼集训 2017 Day1」 解题报告
「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...
- [LOJ 6031]「雅礼集训 2017 Day1」字符串
[LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...
- [LOJ 6030]「雅礼集训 2017 Day1」矩阵
[LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...
- [LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...
随机推荐
- WEB学习-CSS盒模型
盒子的区域 一个盒子中主要的属性就5个:width.height.padding.border.margin. width是“宽度”的意思,CSS中width指的是内容的宽度,而不是盒子的宽度. he ...
- spring解决乱码
spring提供的工具类解决乱码问题 在web.xml配置中添加如下代码: <!--乱码处理--> <filter> <filter-name>encodingFi ...
- MAPZONE GIS SDK接入Openlayers3之五——图形编辑工具
图形编辑工具提供对要素图形进行增.删.改的功能,具体包括以下几种工具类型: 浏览工具 选择工具 创建要素工具 删除命令 分割工具 合并命令 节点编辑工具 修边工具 撤销命令 重做命令 工具的实现基本上 ...
- 【mac】mac上安装JDK
安装步骤就是在Oracle官网下载你想要的JDK版本下载,下载的时候同意协议即可 这里就给出jdk安装的位置 还有一点要注意的是,在指定JVM的位置的时候,需要指定到home目录下
- mac 安装ANT
http://blog.csdn.net/crazybigfish/article/details/18215439 1.下载ant:官网下载 当前最新版是Apache Ant 1.9.3,可以下载那 ...
- Hbase调用JavaAPI实现批量导入操作
将手机上网日志文件批量导入到Hbase中.操作步骤: 1.将日志文件(请下载附件)上传到HDFS中,利用hadoop的操作命令上传:hadoop fs -put input / 2.创建Hbase ...
- PCA主成分分析Python实现
作者:拾毅者 出处:http://blog.csdn.net/Dream_angel_Z/article/details/50760130 Github源代码:https://github.com/c ...
- XMLHttpRequest是什么、如何完整地运行一次GET请求、如何检測错误。
var xmlhttp; function LoadXmlDoc(url){ xmlhttp = null; if(window.XMLHttpRequest){ //code for all new ...
- SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)
--====================================================== --SQL基础-->层次化查询(START BY ... CONNECT BY ...
- iOS常用网络库收集
一 ASIHttpRequest二 AFNetworking 三 AFDownloadRequestOperationA progressive download operation for AFNe ...