zoukankan      html  css  js  c++  java
  • CF436E Cardboard Box 题解

    Problem

    CF436E Cardboard Box

    (n) 个关卡,对每个关卡,你可以花 (a_i) 代价得到一颗星,也可以花 (b_i) 代价得到两颗星,也可以不玩。问获得 (w) 颗星最少需要多少时间。

    Sol

    反悔贪心好题。

    时隔半年终于落实了

    我们考虑如何如何多拿一颗星星:

    1. 0 -> 1(在一个不拿星星的关卡里拿一颗星星)

    2. 1 -> 2

    发现需要反悔才可以。

    于是

    1. 2 -> 1 ,0 -> 2

    2. 1 -> 0 , 0 -> 2

    开 5 个堆记录就行了,细节见代码注释。

    Code

    #define in read()
    #define fi first
    #define se second
    #define pair<int,int> pii
    
    typedef long long ll;
    
    int read(){
    	int x = 0,sgn = 1;char ch = getchar();
    	for(;!isdigit(ch);ch = getchar()) if(ch == '-') sgn = -1;
    	for(;isdigit(ch);ch = getchar()) x = (x<<1)+(x<<3)+(ch^48);
    	return x*sgn;
    }
    
    priority_queue<pii,vector<pii>,greater<pii> > q[5];
    //小根堆
    const int N = 3e5+10;
    const int inf = 0x7fffffff;
    
    int vis[N],a[N],b[N],statu[5] = {0,1,2,1,0};
    ll t[5],th[5]; //血泪的教训,一定要开 long long
    int n,m;
    ll ans;
    /*	
    	q[0] : 0 -> 1
    	q[1] : 1 -> 2
    	q[2] : 2 -> 1
    	q[3] : 1 -> 0
    	q[4] : 0 -> 2
    */
    void add0(int x){
    	q[0].push(pii(a[x],x));
    	q[4].push(pii(b[x],x));
    	vis[x] = 0;
    }
    
    void add1(int x){
    	q[1].push(pii(b[x]-a[x],x));
    	q[3].push(pii(-a[x],x));
    	vis[x] = 1;
    }
    
    void add2(int x){
    	q[2].push(pii(a[x]-b[x],x));
    	vis[x] = 2;
    }
    
    int main (){
    	n = in,m = in;
    	for(int i = 0;i < 5;i++) q[i].push(pii(inf,0));
    	for(int i = 1;i <= n;i++) a[i] = in,b[i] = in,add0(i);
    	for(int i = 1;i <= m;i++){
    		for(int j = 0;j < 5;j++) {
    			t[j] = q[j].top().fi,th[j] = q[j].top().se;
    			while(t[j] < inf && th[j] && statu[j] != vis[th[j]]){
    				q[j].pop(); t[j] = q[j].top().fi,th[j] = q[j].top().se;
    			}
    		}
    		ll minn = inf;
    		minn = min(t[0],min(t[1],min(t[2]+t[4],t[3]+t[4])));
    		if(minn == t[0]){
    			q[0].pop(); add1(th[0]);
    		}else if(minn == t[1]){
    			q[1].pop(); add2(th[1]);
    		}else if(minn == t[2] + t[4]){
    			q[2].pop(); q[4].pop(); add1(th[2]); add2(th[4]);
    		}else{
    			q[3].pop(); q[4].pop(); add0(th[3]); add2(th[4]);
    		}ans += minn;
    	}
    	printf("%lld
    ",ans);
    	for(int i = 1;i <= n;i++) printf("%d",vis[i]);
    	puts("");
    	return 0;
    }
    
    本博客作者:Werner_Yin(https://www.cnblogs.com/werner-yin/) ,转载时请注明出处,谢谢支持!
  • 相关阅读:
    macOS 修改键盘重复按键延迟
    stdout 与 stderr 区别
    E. 1-Trees and Queries
    Codeforces Round #615 (Div. 3)
    Codeforces Round 613(div 2)
    Codeforces Edu80
    SPOJ
    快读
    《货车运输》题解--最大生成树&倍增
    倍增思想求lca
  • 原文地址:https://www.cnblogs.com/werner-yin/p/solution-CF-463E.html
Copyright © 2011-2022 走看看