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」 括号(贪心的更多相关文章

  1. 「HNSDFZ暑期集训 测试1」「LuoguT36488」 连连看

    题目描述 给定一个n × m的矩形地图,每个各自上可能为空,可能有牌,牌上有一个数字. 对于两张同样数字的牌,如果我们可以在地图上用不超过三根水平或竖直,在地图界内,且不经过其他牌的线段将两张牌连起来 ...

  2. loj #6046. 「雅礼集训 2017 Day8」爷

    #6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...

  3. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  4. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

  5. 「雅礼集训 2017 Day2」解题报告

    「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...

  6. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

  7. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  8. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

  9. [LOJ 6029]「雅礼集训 2017 Day1」市场

    [LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...

随机推荐

  1. Cookie 和 Session 有什么区别呢?

    Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等 但如果再往深入探讨的话,就慢慢有一些朋友不太了解了 ...

  2. 一起来学Spring Cloud | 第五章:熔断器 ( Hystrix)

    在微服务项目中,一个系统可以分割成很多个不同的服务模块,不同模块之间我们通常需要进行相互调用.springcloud中可以使用RestTemplate+Ribbon和Feign来调用(工作中基本都是使 ...

  3. BZOJ——2096: [Poi2010]Pilots

    http://www.lydsy.com/JudgeOnline/problem.php?id=2096 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: ...

  4. 输出重定向、cat、系统别名、查看指定行、时间戳

    1.touch命令:如果文件不存在则创建,如存在则更新时间戳;2.除了echo有向文件写入内容的功能,cat也可以; cat > hehe # 输出重定向 cat >> hehe # ...

  5. pnputil

    http://mb.yidianzixun.com/article/0FYSZgnB?s=mb&appid=mibrowser C:\Users\Administrator>pnputi ...

  6. CocoaPods为project的全部target添加依赖支持

    在使用CocoaPods时.pod install默认仅仅能为xcodeproject的第一个target加入依赖库支持.假设要为全部的target添加可依照例如以下步骤进行 两种情 1. 编辑Pod ...

  7. IoT设备程序开发及编译环境搭建初体验

    引言 Mirai事件一经曝出,立即引领了一轮研究IoT设备的热潮.目前,对Mirai的报告大多只是在对其功能实现上的介绍,却很少提及如何实现IoT设备程序开发的测试环境.本文在对Mirai的源码研究的 ...

  8. CF 568A(Primes or Palindromes?-暴力推断)

    A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input st ...

  9. 常见ODBC及OLEDB连接串的写法

    书    名:性能测试进阶指南——LoadRunner11实战 作    者:陈霁 关于数据库连接串的写法

  10. 【转载】读懂IL代码就这么简单(二)

    一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...