51nod1476 括号序列的最小代价
这题应该可以用费用流写吧?不过我想不出贪心来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; }
![](http://file.51nod.com/images/icon/star.png)
![](http://file.51nod.com/images/icon/plus.png)
这里有一个关于合法的括号序列的问题。
如果插入“+”和“1”到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的。例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(()))("是不合法的。我们这有一种仅由“(”,“)”和“?”组成的括号序列,你必须将“?”替换成括号,从而得到一个合法的括号序列。
对于每个“?”,将它替换成“(”和“)”的代价已经给出,在所有可能的变化中,你需要选择最小的代价。
Input
第一行是一个非空的偶数长度的字符串,它仅由“(”,“)”和“?”组成。它的长度不大于 50000。接着是m行,m是字符串中“?”的个数。每一行包含两个整数 ai和bi ( 1<=ai,bi<=1000000), ai是将第i个“?”替换成左括号的代价, bi是将第i个“?”替换成右括号的代价。
Output
在一行中输出合法的括号序列的最小代价。 如果没有答案,输出-1。
Input示例
(??) 1 2 2 8
Output示例
4