专栏文章

题解:P12149 【MX-X11-T3】「蓬莱人形 Round 1」科学

P12149题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipluk1d
此快照首次捕获于
2025/12/03 14:07
3 个月前
此快照最后确认于
2025/12/03 14:07
3 个月前
查看原文

思路

根据最大值最小为首要条件可知用二分。而二分性质向右,因此我们要往左二分。 设球最多 xx 个,则我们可以这样做:把 aixa_i ≤ xaia_i 个球和 aixa_i ≥ xxaix - a_i 个球放到一个待匹配的 vector,再将盒子放到另一个 vector 内,两个数组从小到大排序,从后往前使用小顶堆贪心即可。

代码

CPP
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PII;
ll a[400010];
ll b[400010], w[400010];
PII pt[400010];
int n, m;
vector<ll> wt_ball; // 待匹配
vector<PII> box;
// value id
ll V = 0;
ll ans2 = 0x3f3f3f3f3f3f3f3f;
priority_queue<ll, vector<ll>, greater<ll> >hp;

ll check(ll mid) {
	wt_ball.clear();
	box.clear();
	hp = (priority_queue<ll, vector<ll>, greater<ll> >) {};
	for (int i = 1; i <= n; i++) {
		if (a[i] > mid)
			wt_ball.push_back(a[i] - mid);
		if (a[i] <= mid) {
			wt_ball.push_back(a[i]);
			box.push_back({mid, 0ll});
		}
	}
	for (int i = 1; i <= m; i++) {
		box.push_back({min(mid, b[i]), w[i]});
	}
	sort(wt_ball.begin(), wt_ball.end());
	sort(box.begin(), box.end());
	ll cnt = 0ll;
	int j = box.size() - 1;
	for (int i = wt_ball.size() - 1; i >= 0; i--) {
		while (j >= 0 && box[j].first >= wt_ball[i]) {
			hp.push(box[j].second), j--;
		}
		if (hp.size() == 0) {
			return 0;
		}
		cnt += hp.top();
		hp.pop();
	}
//	printf("===%lld %lld\n", mid, cnt);
	return cnt;
}

signed main() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]), V = max(V, a[i]);
	for (int i = 1; i <= m; i++) {
		ll x, y;
		scanf("%lld%lld", &x, &y);
		b[i] = x, w[i] = y;
	}
	ll l = 1, r = V;
	while (l < r) {
		ll mid = (l + r) / 2;
		ll t = check(mid);
		if (t)
			r = mid, ans2 = t;
		else
			l = mid + 1;

	}
	printf("%lld %lld", r, check(r));
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...