题解:CF436E Cardboard Box

题意:给出 \(n\) 个关卡,你可以花费 \(a_i\) 代价在 \(i\) 关卡获得一颗星,或者花费 \(b_i\) 获得两颗星,求得到 \(k\) 颗星的最小代价,并给出构造。

做法:很明显是反悔贪心。

那么我们考虑每一颗星有几种更新方式。

  1. 花费 \(a_i\) 代价获得 \(1\) 颗星,代价 \(a_i\)。需要维护零个星中 \(a_i\) 的最小值。

  2. \(b_i - a_i\) 代价把一个 \(1\) 星升成 \(2\) 星,代价 \(b_i - a_i\)。需要维护一颗星中 \(b_i\) 的最小值。

  3. 将一个 \(2\) 星变成 \(1\) 星,将一个 \(0\) 星变成 \(2\) 星,代价 \(b_i - (b_j - a_j)\)。需要维护两颗星中 \(b_i - a_i\) 的最大值和 \(0\) 颗星中 \(b_i\) 最小的。

  4. 将一个 \(1\) 星变成 \(0\) 星,将一个 \(0\) 星变成 \(2\) 星,代价 \(b_i - a_j\),需要维护 \(1\) 颗星中 \(a_i\) 最大的和 \(0\) 颗星中 \(b_i\) 最小的。

用五个堆维护上述操作即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5 + 5;
struct node {
	int p, val;
	friend bool operator<(node x, node y) {
		return x.val > y.val;
	}
};
priority_queue<node> p[6]; // a min, (bi - ai) min, b min, ai max, (bi - ai) max
// 选了 0, 选了 1,选了 0,选了 1 个,选了 2 个 
int n, m, a[maxn], b[maxn], use[maxn], res;
int solve1() {
	while(!p[1].empty() && use[p[1].top().p] != 0)
		p[1].pop(); 
	if(p[1].empty())
		return 9e18;
	return p[1].top().val;
}
int solve2() {
	while(!p[2].empty() && use[p[2].top().p] != 1)
		p[2].pop();
	if(p[2].empty())
		return 9e18;
	return p[2].top().val;
}
int solve3() {
	while(!p[3].empty() && use[p[3].top().p] != 0)
		p[3].pop();
	while(!p[4].empty() && use[p[4].top().p] != 1)
		p[4].pop();
	if(p[4].empty() || p[3].empty())
		return 9e18;
	return p[3].top().val + p[4].top().val;
}
int solve4() {
	while(!p[3].empty() && use[p[3].top().p] != 0)
		p[3].pop();
	while(!p[5].empty() && use[p[5].top().p] != 2)
		p[5].pop();
	if(p[5].empty() || p[3].empty())
		return 9e18;
	return p[3].top().val + p[5].top().val;
}
void renew1() {
	node x = p[1].top(); p[1].pop();
	use[x.p] = 1;
	p[2].push(node{x.p, b[x.p] - a[x.p]});
	p[4].push(node{x.p, -a[x.p]});
}
void renew2() {
	node x = p[2].top(); p[2].pop();
	use[x.p] = 2;
	p[5].push(node{x.p, a[x.p] - b[x.p]});
}
void renew3() {
	node x = p[4].top(), y = p[3].top(); p[4].pop(), p[3].pop();
	use[x.p] = 0, use[y.p] = 2;
	p[1].push(node{x.p, a[x.p]}), p[3].push(node{x.p, b[x.p]});
	p[5].push(node{y.p, a[y.p] - b[y.p]});
}
void renew4() {
	node x = p[5].top(), y = p[3].top(); p[5].pop(), p[3].pop();
	use[x.p] = 1, use[y.p] = 2;
	p[2].push(node{x.p, b[x.p] - a[x.p]}), p[4].push(node{x.p, -a[x.p]});
	p[5].push(node{y.p, a[y.p] - b[y.p]});
}
signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i] >> b[i];
	for (int i = 1; i <= n; i++)
		p[1].push(node{i, a[i]}), p[3].push(node{i, b[i]});
	for (int i = 1; i <= m; i++) {
		int ans = 9e18, p = 0;
		int v[5] = {0, solve1(), solve2(), solve3(), solve4()};
		for (int j = 1; j <= 4; j++) {
			if(ans > v[j])
				ans = v[j], p = j;
		}
		res += ans;
	//	cout << i << " " << p << endl;
		if(p == 1)
			renew1();
		if(p == 2)
			renew2();
		if(p == 3)
			renew3();
		if(p == 4)
			renew4();
	}
	cout << res << endl;
	for (int i = 1; i <= n; i++)
		cout << use[i];
	cout << endl;
	return 0;
}
posted @ 2025-07-22 21:28  LUlululu1616  阅读(10)  评论(0)    收藏  举报