51node1476 括号序列的最小代价(贪心)

来源:互联网 发布:浪潮软件官网 编辑:程序博客网 时间:2024/06/05 11:02

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");    }}
0 0