题目

源地址:

http://codeforces.com/contest/3/problem/D

理解

比赛的时候没有做出来,赛后看了琦神的解题报告才明白应该怎么敲。 实际上这个题目需要解决两个问题:第一是合法性,也就是是否满足左右括号匹配;第二是最优化,也就是要求Cost消耗最小。 使用一个变量cnt遍历输入的字符串,遇到'('则自增,遇到')'则自减。这样,只要判断cnt是否为零,就能判断是不是合法。一开始的时候将每一个'?'都重置为')',然后维护一个保存左右括号消耗差和当前节点的优先队列。然后开始不断地从优先队列中取出键对,使用保存了所有右括号消耗和的ss变量去减。 经过这样的处理之后,cnt只有两种情况。cnt不为零时,说明不可能合法,输出"-1",cnt为零时,说明有解,输出ss以及最后符合要求的字符串。

代码


#define MAXN 50000+10

char s[MAXN];
ll ss;
int cnt;
int a,b;

priority_queue<pair<ll, int> > que;

int main(int argc, char const *argv[])
{
    scanf("%s", s+1);
    ss=0,cnt=0;
    for(int i=1; s[i]; i++)
    {
        if(s[i]=='(')
        {
            cnt++;
        }
        else if(s[i]==')')
        {
            cnt--;
        }
        else
        {
            scanf("%d%d", &a,&b);
            ss+=b;
            cnt--;
            s[i]=')';
            que.push(pair<ll,int> (b-a,i));
        }
        if(cnt<0)
        {
            if(que.empty()) break;
            pair<ll,int> f = que.top();
            que.pop();
            ss-=f.first;
            cnt+=2;
            s[f.second]='(';
        }
    }
    if(cnt!=0)
        printf("-1\n");
    else
        printf("%lld\n%s\n", ss,s+1);
    return 0;
}

更新日志

  • 2014年11月3日 已AC。