版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/89737507
给定一个由‘(’,’)‘以及’?'构成的字符串
替换第 个括号变成左括号耗费 ,变成右括号耗费
现在你要替换一些’?‘,使这个序列变成合法的序列且代价和最小
下面是关于合法序列的定义和性质:
- 一个空串是一个合法序列
- 若 是一个合法序列,则( )也是一个合法序列
- 若 都是合法序列,则 也是一个合法序列
数据范围:
字符串长度
这是一道比较简单的贪心题,首先默认所有问号为右括号,当当前的左括号数小于右括号时,则从之前找到代价最小的问号变成的右括号代替即可,正确性显然。
代价最小的这个过程可以用堆,时间复杂度
#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;int l,n,a,b;
long long ans;
char s[50001];
struct node{int x,id;};
inline bool operator <(const node &x,const node &y){return x.x<y.x;}
priority_queue<node>q;
inline int read()
{
char c;int f=0,d=1;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
signed main()
{
scanf("%s",s);
n=strlen(s);
for(register int i=0;i<n;i++)
{
if(s[i]=='(') {l++;continue;}//l表示当前左右括号的差值
else
{
if(s[i]=='?')
{
a=read();b=read();
q.push((node){b-a,i});//把替换代价放入小根堆
s[i]=')';
ans+=b;
}
if(--l<0)//替换成右括号,l--
{
if(q.empty()) return puts("-1")&0;
ans-=q.top().x;//减去最小替换代价
s[q.top().id]='(';
l+=2;
q.pop();
}
}
}
if(l) return puts("-1")&0;
//注意判断序列本来就不合法的情况,刚开始就是因为这个WA了第48个点
printf("%I64d\n%s",ans,s);//输出
}
后记——一些想法
注意:以下内容并非本题解法,只是记录原有思路
刚开始想着去
设 表示前i个位置,当前左括号与右括号的差值为j时的最小代价
当第i位是左括号时,
当第i位是右括号时,
当第i为是?时,
扫描二维码关注公众号,回复:
6198891 查看本文章
终点
酱紫的时间复杂度和空间复杂度都是 ,不过可以用滚动数组将空间复杂度压缩到 ,对于时间复杂度,我的想法是记录当前最大的左右括号差值,这样子的最坏时间复杂度是
不过由于笔者没有想到保存路径的方法, 所以这种想法就被搁置了,如果各位大爷有比较好的想法可以推荐一下呀QWQ