湘潭邀请赛
codeforces#3D. Least Cost Bracket Sequence
题意
给一个未完全填好的括号序列,每一个可填充的位置,填(的花费为a,填)的花费为b,求使其成合法序列的最小花费
分析
合法的括号序列有一个特点:对于任意位置 i ,它的左括号的数量不能少于 ceil ((i+1)/2)。首先强制将所有都变为),然后从前往后模拟这个过程,用一个优先队列维护即可。
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn = 5e4+10; struct node { int id, ans; bool friend operator < (node a, node b) { // if(a.ans != b.ans) return a.ans < b.ans; } }k[maxn]; priority_queue<node>q; bool vis[maxn]; ll sum = 0; int a[maxn]; int b[maxn]; int n; int main() { string s; cin>>s; int len = s.size(); int num = 0; int cnt = 0; for(int i = 0 ; i < len; i++) { if(s[i] == ‘?‘) n++; else if(s[i] == ‘)‘) cnt++; } for(int i = 1; i <= n; i++) { scanf("%d%d", &a[i], &b[i]); sum += 1ll*b[i]; } int kl = 0; int oo = 0; for(int i = 0; i < len; i++) { if(s[i] == ‘(‘) kl++; else { if(s[i] == ‘?‘) { ++oo; k[++num].id = i; k[num].ans = b[oo]-a[oo]; q.push(k[num]); } while(kl < (ceil((1.0*(i+1))/2.0)) && q.size()>0) { node kk = q.top(); q.pop(); sum -= 1ll*kk.ans; vis[kk.id]=1; kl++; } } } int num1 = 0, num2 = 0; for(int i = 0; i < len; i++) { if(s[i] == ‘(‘) num1++; else if(s[i] == ‘)‘) num2++; else { if(vis[i] == 1) num1++; else num2++; } if(num2 > num1) { cout<<"-1"<<endl; return 0; } } if(num1 != num2) { cout<<"-1"<<endl; return 0; } printf("%I64d\n", sum); for(int i = 0; i < len; i++) { if(s[i]!=‘?‘) cout<<s[i]; else { if(vis[i] == 1) cout<<‘(‘; else cout<<‘)‘; } } return 0; }
时间: 2024-10-19 14:58:21