cf1607 H. Banquet Preparations 2(贪心)
https://codeforces.com/contest/1607/problem/H
题意:
每个盘子里有ai个白球和bi个黑球。现要从每个盘子里拿走mi个球,使不同的盘子数量最小。两个盘子相等是指白球和黑球的个数分别相等。题目保证每个盘子里的球数不少于m
思路:
对于任意两个盘子,只有当它们的 \(a_i+b_i-m_i\) 相等时才有可能让这两个盘子相等。
考虑一组 \(a_i+b_i-m_i\) 相等的盘子。每个盘子剩下的白球有一个最小值和最大值,且这个盘子剩下的白球数能取到中间的任一值。可以处理出每个盘子区间 \([l_i,r_i]\) ,问题转化为在数轴中取尽量少的点,使每个区间都至少包含一个点。区间按右端点排序然后贪心取右端点即可
#include <bits/stdc++.h>
using namespace std;
const signed N = 2e5+10;
struct Dish
{
int id, a, b, m, l, r, res;
void read(int i)
{
id = i; cin >> a >> b >> m;
l = a - min(a, m), r = a - max(0, m - b);
res = a + b - m;
}
bool operator< (const Dish &t)
{
if(res != t.res) return res < t.res;
else return r < t.r;
}
} dish[N];
pair<int, int> ans[N];
signed main()
{
int T; cin >> T; while(T--)
{
int n; cin >> n;
for(int i = 1; i <= n; i++) dish[i].read(i);
sort(dish + 1, dish + 1 + n); dish[0].res = -1;
int cnt = 0, nowr = 0;
for(int i = 1; i <= n; i++)
{
if(dish[i].res != dish[i-1].res || dish[i].l > nowr)
cnt++, nowr = dish[i].r;
ans[dish[i].id].first = dish[i].a - nowr;
ans[dish[i].id].second = dish[i].m - ans[dish[i].id].first;
}
cout << cnt << '\n';
for(int i = 1; i <= n; i++)
cout << ans[i].first << ' ' << ans[i].second << '\n';
}
return 0;
}

浙公网安备 33010602011771号