codeforces 436E Cardboard Box 题解

题目传送门

题目大意: n n n 轮游戏,第 i i i 轮游戏拿 1 1 1 颗星的代价为 a i a_i ai,拿 2 2 2 颗星的代价为 b i b_i bi,不拿代价为 0 0 0,问拿到恰好 w w w 颗星的最小代价。

题解

考虑带反悔策略的贪心。

增加一颗星时,有四种情况:

  1. 把一个 0 0 0 星变成 1 1 1 星,代价增加 a i a_i ai
  2. 把一个 1 1 1 星变成 2 2 2 星,代价增加 b i − a i b_i-a_i biai
  3. 把一个 1 1 1 星变成 0 0 0 星,把另一个 0 0 0 星变成 2 2 2 星,代价为 b j − a i b_j-a_i bjai
  4. 把一个 2 2 2 星变成 1 1 1 星,把另一个 0 0 0 星变成 2 2 2 星,代价为 b j − ( b i − a i ) b_j-(b_i-a_i) bj(biai)

于是用小根堆维护 a i   ,   b i − a i   ,   b j   ,   − a i   ,   − ( b i − a i ) a_i~,~b_i-a_i~,~b_j~,~-a_i~,~-(b_i-a_i) ai , biai , bj , ai , (biai),每次取四种中最优即可。

代码如下:

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define maxn 300010
#define ll long long
#define inf 100000000000000ll

int n,k,a[maxn],b[maxn];
struct par{
    
    ll val;int pos;};
struct cmp{
    
    
	bool operator ()(const par A,const par B)const
	{
    
    return A.val>B.val;}
};
priority_queue< par,vector<par>,cmp > q1,q2,q3,q4,q5;
int ans[maxn];ll tot=0;
void add0(int x){
    
    
	ans[x]=0;
	q1.push((par){
    
    a[x],x});
	q3.push((par){
    
    b[x],x});
}
void add1(int x){
    
    
	ans[x]=1;
	q2.push((par){
    
    b[x]-a[x],x});
	q4.push((par){
    
    -a[x],x});
}
void add2(int x){
    
    
	ans[x]=2;
	q5.push((par){
    
    a[x]-b[x],x});
}

int main()
{
    
    
	scanf("%d %d",&n,&k);
	q1.push((par){
    
    inf,0});
	q2.push((par){
    
    inf,0});
	q3.push((par){
    
    inf,0});
	q4.push((par){
    
    inf,0});
	q5.push((par){
    
    inf,0});
	for(int i=1;i<=n;i++){
    
    
		scanf("%d %d",&a[i],&b[i]);
		add0(i);
	}
	while(k--){
    
    
		int p1=q1.top().pos,p2=q2.top().pos,p3=q3.top().pos,p4=q4.top().pos,p5=q5.top().pos;
		while(q1.size()>1&&ans[p1]!=0)q1.pop(),p1=q1.top().pos;
		while(q2.size()>1&&ans[p2]!=1)q2.pop(),p2=q2.top().pos;
		while(q3.size()>1&&ans[p3]!=0)q3.pop(),p3=q3.top().pos;
		while(q4.size()>1&&ans[p4]!=1)q4.pop(),p4=q4.top().pos;
		while(q5.size()>1&&ans[p5]!=2)q5.pop(),p5=q5.top().pos;
		ll t1=q1.top().val;
		ll t2=q2.top().val;
		ll t3=q3.top().val+q4.top().val;
		ll t4=q3.top().val+q5.top().val;
		ll mi=min(min(t1,t2),min(t3,t4));tot+=mi;
		if(t1==mi){
    
    
			q1.pop();
			add1(p1);
		}else if(t2==mi){
    
    
			q2.pop();
			add2(p2);
		}else if(t3==mi){
    
    
			q3.pop();q4.pop();
			add2(p3);add0(p4);
		}else{
    
    
			q3.pop();q5.pop();
			add2(p3);add1(p5);
		}
	}
	printf("%lld\n",tot);
	for(int i=1;i<=n;i++)printf("%d",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/a_forever_dream/article/details/109370658