• 【贪心】【CF3D】 Least Cost Bracket Sequence


    传送门

    Description

    给一个序列,序列里面会有左括号、问号、右括号。对于一个(?)而言,可以将其替换为一个((),也可以替换成一个()),但是都有相应的代价。问:如何替换使得代价最小。前提是替换之后的序列中,括号是匹配的。如果不能替换为一个括号匹配的序列则输出-1。

    Input

    第一行是序列,序列长度不超过(5~ imes10^4),下面m(m是(m)的数量)行有每行(2)个数据,第一个是(()的代价,第2个是())的代价

    Output

    第一行输出最小代价

    第二行输出被转换的序列

    Sample Input

    (??)
    1 2
    2 8
    

    Sample Output

    4
    ()()
    

    Solution

    显然DP可做,然而数据范围太大。

    DP不能就尝试一下贪心。

    考虑一个特殊性质:对于一个括号序列,如果想要保证他合法,则必须保证在任意一个位置,其前缀左括号数必须不小于右括号数。否则一定不合法。同时这个条件是括号序列合法的充要条件。于是考虑按照这个性质贪心,对于任意一个可以修改的位置,贪心的修改成右括号。当序列不合法时,贪心选取修改代价最小的位置改成左括号。因为修改左括号不会使序列不合法,所以这个贪心使正确的。

    Code

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #define rg register
    #define ci const int
    #define cl const long long int
    
    typedef long long int ll;
    
    namespace IO {
        char buf[90];
    }
    
    template<typename T>
    inline void qr(T &x) {
        rg char ch=getchar(),lst=' ';
        while(ch>'9'||ch<'0') lst=ch,ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        if(lst=='-') x=-x;
    }
    
    template<typename T>
    inline void qw(T x,const char aft,const bool pt) {
        if(x<0) x=-x,putchar('-');
        int top=0;
        do {
            IO::buf[++top]=x%10+'0';
            x/=10;
        } while(x);
        while(top) putchar(IO::buf[top--]);
        if(pt) putchar(aft);
    }
    
    template<typename T>
    inline T mmax(const T a,const T b) {return a > b ? a : b;}
    template<typename T>
    inline T mmin(const T a,const T b) {return a < b ? a : b;}
    template<typename T>
    inline T mabs(const T a) {return a < 0 ? -a : a;}
    
    template<typename T>
    inline void mswap(T &a,T &b) {
        T temp=a;a=b;b=temp;
    }
    
    const int maxn = 50010;
    
    struct M {
    	int l,r;
    };
    M MU[maxn];
    
    struct Zay {
    	int pos,v;
    	inline bool operator<(const Zay &_others) const {
    		return this->v > _others.v;
    	}
    	Zay (ci _a=0,ci _b=0) {pos=_a,v=_b;}
    };
    
    char st[maxn];
    std::priority_queue<Zay>Q;
    
    int main() {
    	scanf("%s",st+1);
    	int l=strlen(st+1);
    	if(l&1) return puts("-1")&0;
    	for(rg int i=1;i<=l;++i) if(st[i] == '?') {
    		qr(MU[i].l);qr(MU[i].r);
    	}
    	rg int cnt=0;ll _ans=0;
    	for(rg int i=1;i<=l;++i) {
    		if(st[i] == '(') ++cnt;
    		else if(st[i] == ')') --cnt;
    		else {
    			--cnt;Q.push(Zay(i,MU[i].l-MU[i].r));
    			st[i]=')';_ans+=MU[i].r;
    		}
    		while(cnt<0) {
    			if(Q.empty()) return puts("-1")&0;
    			int h=Q.top().pos;Q.pop();
    			_ans+=MU[h].l-MU[h].r;
    			st[h]='(';
    			cnt+=2;
    		}
    	}
    	if(cnt > 0) return puts("-1")&0;
    	qw(_ans,'
    ',true);
    	printf("%s",st+1);
    	return 0;
    }
    

    Summary

    可能需要贪心时,寻找题目的特殊性质,按照特殊性质进行贪心。

  • 相关阅读:
    Kafka如何保证读写的跨分区与会话
    Kafka topic中的partition的leader选举
    Kafka为什么这么快
    sqoop导入导出
    为什么要用redis去重
    bypass SortShuffleManager的bypass运行机制
    大数据常用端口号
    vector基础
    【拓扑排序】
    【POJ】Crazy Search(hash)
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/9806351.html
Copyright © 2020-2023  润新知