CF3D Least Cost Bracket Sequence

【题目链接】

失踪人口回归

题意分析

每一个问号 都可以被填为左括号或者右括号 并且有相应的代价

要求使用最小的代价使得最后的序列左右括号是匹配的 如果实在无法匹配就输出"-1"

这里的话 有一个非常有意思的思路 一开始把所有问号都填成右括号 然后顺序扫描 遇到无法匹配的情况的话 就把问号修改为左括号

那么如果做到代价最小呢 只要我们维护一下之前问号情况 看看哪一个由右括号变成左括号需要的代价是最小的就可以了 这个我们可以使用堆来维护

那么什么情况是硬核无法匹配呢?

1.问号全部填成左括号或者右括号 还是无法满足数量差

2.初始字符串开头就是右括号或者末尾就是左括号

3.最后填完之后无法做到数量相当

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define M 1008611
#define Pa pair<int,int>
using namespace std;
int len,nl,nr,tot;
long long ans;
char s1[M],s2[M];
int cdy[M],wzy[M];
priority_queue<Pa,vector<Pa >,greater<Pa > > que;
int main()
{
	scanf("%s",s1+1);len=strlen(s1+1);
	for(int i=1;i<=len;++i)
	{
		if(s1[i]=='?')
		{
			scanf("%d%d",&cdy[i],&wzy[i]);
			s2[i]=')';
			++tot;
		}
		else
		{
			s2[i]=s1[i];
			if(s1[i]=='(') nl++;
			if(s2[i]==')') nr++;
		}
	}
	if(s1[1]==')'||s1[len]=='(')
	{
		printf("-1");
		return 0;
	}
	if(abs(nl-nr)>tot)
	{
		printf("-1");
		return 0;
	}
	if(s1[1]=='?') s2[1]='(';
	nl=nr=0;
	for(int i=1;i<=len;++i)
	{
		if(s2[i]=='(') ++nl;
		if(s2[i]==')') ++nr; 
		if(s1[i]=='?'&&i!=1) que.push(make_pair(cdy[i]-wzy[i],i));
		if(nr>nl)
		{
			int now=que.top().second;que.pop();
			s2[now]='(';
			--nr;++nl;
		}
	}
	if(nl!=nr) 
	{
		printf("-1");
		return 0;
	}
	for(int i=1;i<=len;++i)
	if(s1[i]=='?')
	{
		if(s2[i]=='(') ans+=cdy[i];
		if(s2[i]==')') ans+=wzy[i];
	}
	printf("%lld
",ans);
	for(int i=1;i<=len;++i) putchar(s2[i]);
	return 0;
} 
原文地址:https://www.cnblogs.com/LovToLZX/p/14307658.html