这题应该可以用费用流写吧?不过我想不出贪心来TAT。其实还是单调队列乱搞啊T_T
//ÍøÉϵÄÌ°ÐÄËã·¨ºÃÉñ°¡¡£¡£¡£ÎÒÖ»»áÓÃ×îС·ÑÓÃ×î´óÁ÷ÅÜTAT
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
int x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x;
}
priority_queue<int>q;
const int nmax=5e4+5;
const int inf=0x7f7f7f7f;
int a[nmax];char s[nmax];
int main(){
scanf("%s",s+1);
int n=strlen(s+1),u,v,cnt=0;long long sm=0;
rep(i,1,n) if(s[i]=='?') u=read(),v=read(),sm+=v,a[i]=v-u;
rep(i,1,n){
if(s[i]=='(') ++cnt;else --cnt;
if(s[i]=='?') q.push(a[i]);
if(cnt<0) {
if(q.empty()) {
puts("-1");return 0;
}else sm-=q.top(),q.pop(),cnt+=2;
}
}
if(cnt) puts("-1");
else printf("%lld\n",sm);
return 0;
}
收藏
关注
这里有一个关于合法的括号序列的问题。
如果插入“+”和“1”到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的。例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的。我们这有一种仅由“(”,“)”和“?”组成的括号序列,你必须将“?”替换成括号,从而得到一个合法的括号序列。
对于每个“?”,将它替换成“(”和“)”的代价已经给出,在所有可能的变化中,你需要选择最小的代价。
Input
第一行是一个非空的偶数长度的字符串,它仅由“(”,“)”和“?”组成。它的长度不大于 50000。接着是m行,m是字符串中“?”的个数。每一行包含两个整数 ai和bi ( 1<=ai,bi<=1000000), ai是将第i个“?”替换成左括号的代价, bi是将第i个“?”替换成右括号的代价。
Output
在一行中输出合法的括号序列的最小代价。
如果没有答案,输出-1。
Input示例
(??)
1 2
2 8
Output示例
4