zoukankan      html  css  js  c++  java
  • 【题解】 CF436E Cardboard Box 带悔贪心

    Legend

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

    (1 le n le 3 imes 10^5)(1 le a_i < b_i le 10^9)(1 le w le 2n)

    Link ( extrm{to Codeforces})

    Editorial

    这个贪心方法感觉和 [NOI2019]序列 挺像的。

    考虑每次只增加一颗星,进行下列操作的哪一个:

    • 得到某个关卡的第一颗星,花费 (a_i)
    • 得到某个关卡的第二颗星,花费 (b_i-a_i)
    • 直接得到某个关卡的两颗星,并去掉某个关卡的一颗星,花费 (a_i+(b_i-a_i)-max(a_j,b_k))

    不难发现,上述值都可以使用堆来进行维护。

    Code

    #include <bits/stdc++.h>
    
    #define debug(...) fprintf(stderr ,__VA_ARGS__)
    #define __FILE(x)
    	freopen(#x".in" ,"r" ,stdin);
    	freopen(#x".out" ,"w" ,stdout)
    #define LL long long
    
    const int MX = 3e5 + 23;
    
    using namespace std;
    
    int read(){
    	char k = getchar(); int x = 0;
    	while(k < '0' || k > '9') k = getchar();
    	while(k >= '0' && k <= '9') x = x * 10 + k - '0' ,k = getchar();
    	return x;
    }
    
    int vis[MX] ,n ,w;
    LL a[MX] ,b[MX];
    
    struct nodeA{bool operator()(int x ,int y){return a[x] < a[y];}};
    struct revnodeA{bool operator()(int x ,int y){return a[x] > a[y];}};
    struct nodeB{bool operator()(int x ,int y){return b[x] < b[y];}};
    struct revnodeB{bool operator()(int x ,int y){return b[x] > b[y];}};
    struct nodeAB{bool operator()(int x ,int y){return a[x] + b[x] > a[y] + b[y];}};
    
    priority_queue<int ,vector<int> ,nodeA> A; // 取最大的
    priority_queue<int ,vector<int> ,revnodeA> rA; // 取最小的
    priority_queue<int ,vector<int> ,nodeB> B;
    priority_queue<int ,vector<int> ,revnodeB> rB;
    priority_queue<int ,vector<int> ,nodeAB> rAB;
    
    int main(){
    	n = read() ,w = read();
    	for(int i = 1 ; i <= n ; ++i){
    		a[i] = read() ,b[i] = read() - a[i];
    		rA.push(i) ,rAB.push(i);
    	}
    	
    	LL ans = 0;
    	for(LL i = 1 ,v1 ,v2 ,v3 ; i <= w ; ++i){
    		while(!A.empty() && (!(vis[A.top()] & 1) || (vis[A.top()] & 2))) A.pop();
    		while(!rA.empty() && (vis[rA.top()] & 1)) rA.pop();
    		while(!B.empty() && (vis[B.top()] & 3) != 3) B.pop();
    		while(!rB.empty() && ((vis[rB.top()] & 2) || !(vis[rB.top()] & 1))) rB.pop();
    		while(!rAB.empty() && vis[rAB.top()]) rAB.pop();
    
    		v1 = v2 = v3 = LLONG_MAX;
    
    		if(!rA.empty()) v1 = a[rA.top()];
    		if(!rB.empty()) v2 = b[rB.top()];
    		if(!rAB.empty()){
    			if(!A.empty()) v3 = std::min(v3 ,a[rAB.top()] + b[rAB.top()] - a[A.top()]);
    			if(!B.empty()) v3 = std::min(v3 ,a[rAB.top()] + b[rAB.top()] - b[B.top()]);
    		}
    		LL best = min(min(v1 ,v2) ,v3);
    		ans += best;
    
    		if(v1 == best){
    			vis[rA.top()] |= 1;
    			A.push(rA.top());
    			rB.push(rA.top());
    			continue;
    		}
    		if(v2 == best){
    			vis[rB.top()] |= 2;
    			B.push(rB.top());
    			continue;
    		}
    		if(v3 == best){
    			if(v3 == a[rAB.top()] + b[rAB.top()] - a[A.top()]){
    				vis[rAB.top()] = 3;
    				vis[A.top()] &= -1 ^ 1;
    				rAB.push(A.top());
    				rA.push(A.top());
    			}
    			else{
    				vis[rAB.top()] = 3;
    				vis[B.top()] &= -1 ^ 2;
    				rB.push(B.top());
    				A.push(B.top());
    			}
    		}
    	}
    
    	printf("%lld
    " ,ans);
    	for(int i = 1 ; i <= n ; ++i)
    		printf("%d" ,(vis[i] & 1) + ((vis[i] >> 1) & 1));
    	puts("");
    
    	return 0;
    }
    
    // very nice greedy problem
    
  • 相关阅读:
    XP系统忘记密码解决方法
    实现一个简易的IoC框架(上)(此篇与Spring.NET无关,为自己手写IoC框架)
    Spring.NET教程(三)——对象的创建(基础篇)
    Spring.NET教程(二)——环境搭建(基础篇)
    Spring.NET教程(一)——控制反转(依赖注入)(基础篇)(转)
    递归与迭代
    软件研发人员考核的十项基本原则(转)
    ORACLE多表关联的update语句
    软件质量的分层控制方法
    技术研究与工程开发(转)
  • 原文地址:https://www.cnblogs.com/imakf/p/14321454.html
Copyright © 2011-2022 走看看