51node1476
题目
中文题目
思路
先假设所有的?都是),记s是前缀和,遇到(+1,遇到)-1,如果s小于0,那么表示必须要有变化了,而且这样之前累计的?最多,取优先队列中存的最小的从右括号变到左括号的值,并且s+=2即可。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=50010;
char s[maxn];
ll a[maxn],b[maxn];
int pos[maxn];
priority_queue<ll,vector<ll>,greater<ll> > q;
int main()
{
ll ans=0;
int cnt=0;
while(!q.empty()) q.pop();
scanf("%s",s);
int len=strlen(s);
for(int i=0; i<len; i++)
{
if(s[i]=='?')
{
pos[i]=cnt++;
}
}
for(int i=0; i<cnt; i++)
{
scanf("%I64d %I64d",&a[i],&b[i]);
ans+=b[i];
}
ll aim=0;
int flag=0;
for(int i=0; i<len; i++)
{
if(s[i]=='(')
{
aim++;
}
else if(s[i]==')')
{
aim--;
}
else if(s[i]=='?')
{
aim--;
q.push(a[pos[i]]-b[pos[i]]);
}
if(aim<0)
{
if(q.empty())
{
printf("-1\n");
flag=1;
break;
}
else
{
ans+=q.top();
q.pop();
aim+=2;
}
}
}
if(!flag)
{
if(aim==0) printf("%I64d\n",ans);
else printf("-1\n");
}
}