51nod 1476 括号序列的最小代价(贪心+优先队列)

题意

我们这有一种仅由“(”,“)”和“?”组成的括号序列,你必须将“?”替换成括号,从而得到一个合法的括号序列。
对于每个“?”,将它替换成“(”和“)”的代价已经给出,在所有可能的变化中,你需要选择最小的代价。

思路

刚开始\(?\)全部看做\()\),然后从左到右扫一遍,发现\()\)\((\)多的时候,就从优先队列里弹出一个最小代价的改变。

代码

# include<bits/stdc++.h>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-8
# define MOD 100000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(register int i=a; i<=n; ++i)
# define FDR(i,a,n) for(register int i=a; i>=n; --i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline char nc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int Scan(){
    char ch=nc();int sum=0, f=1;
    if (ch=='-') f=-1, ch=nc();
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum*f;
}
const int N=50005;
//Code begin....

struct Node{int x, y;}node[N];
char s[N];
priority_queue<int,VI,greater<int> >que;

int main ()
{
    int num=0;
    LL ans=0;
    scanf("%s",s+1);
    int n=strlen(s+1);
    for (int i=1; s[i]; ++i) if (s[i]=='?') ++num;
    FOR(i,1,num) scanf("%d%d",&node[i].x,&node[i].y), ans+=node[i].y;
    int p=0, down=0, cnt=0;
    for (int i=1; s[i]; ++i) {
        if (s[i]=='(') ++down;
        else {
            if (s[i]=='?') ++p, que.push(node[p].x-node[p].y);
            else ++cnt;
            if (down) --down;
            else if (!que.empty()) ans+=que.top(), que.pop(), ++down;
            else {puts("-1"); return 0;}
        }
    }
    if (cnt+que.size()!=n/2) puts("-1");
    else printf("%lld\n",ans);
    return 0;
}
posted @ 2017-08-30 23:31  free-loop  阅读(377)  评论(0编辑  收藏  举报