CCPC省赛的时候和队友讨论了多值同时贪心怎么最优, 没整出来, 今天就碰到这种题了。。。
私以为贪心不是特别容易凭空构造出一种严谨/正确的贪心方案
我这种铁牌选手只能多看多学吧,没什么别的方法
题目:
给定N个二元组(a1,b1),(a2,b2),…,(aN,bN),请你从中选出恰好K个,使得ai的最小值与bi的最小值之和最大。
请输出ai的最小值与bi的最小值之和
解法:
先贪心一个值, 然后动态贪心第二个值, 类似二分答案
按a 或 b值从大到小排序
然后从前先后遍历, 维护一个答案小顶堆(里面是另一个值)
易证:若堆体积大于k 弹出的堆顶必然不是最优解,
当体积等于k时 堆顶必然是当前1 - now中 b值的范围最优解,
arr[now].fst 也是最优解 (开始已排序固定)
最后动态更新答案既为正确值
代码
const int MAXN = 1e6 + 10;
struct node
{
ll fst, lst;
}arr[MAXN];
bool cmp(node a, node b)
{
return a.fst > b.fst;
}
priority_queue <ll, vector<ll>, greater<ll> > PQ;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
ll n, k;
cin >> n >> k;
for(int i = 0; i < n; ++i)
{
cin >> arr[i].fst >> arr[i].lst;
}
sort(arr, arr + n, cmp);
ll ans = -INF;
for(int i = 0; i < n; ++i)
{
PQ.push(arr[i].lst);
if(PQ.size() > k)
PQ.pop();
if(PQ.size() == k)
{
ans = max(ans, PQ.top() + arr[i].fst);
}
}
cout << ans << '
';
return 0;
}