【Codeforces】#657 C.Choosing flowers 枚举 二分
题目链接
题意
某个男人要为他老婆买 n 朵花,现在花店有 m 种花,每种花都有两个属性,a,b。a 表示当其老婆第一次收到该种花获得的幸福度,b 表示当其老婆第 2、3···次收到该花的时候收获的幸福度。
问其老婆的收获的最高幸福度是多少?
错误思路
贪心题。
肯定只会有一种花会被送多次
这时把 a 大于等于\(max(b)\) 的都取了。
然后枚举哪种花会被取多次,成功 WA 掉
正解
只会有一种花被送多次,这是肯定的。
当前枚举第 \(i\) 朵花会被取多次,如果存在 \(a_j \geq b_i\) ,那么第 \(j\) 朵花就要被取一次,如果所有的 \(j\) 被取完之后,还可以接着取,那么就把剩下的次数全部取第 \(i\) 朵花。
取最大值。
代码
/*
* @Autor: valk
* @Date: 2020-08-11 12:38:37
* @LastEditTime: 2020-08-15 17:06:38
* @Description: 如果邪恶 是 华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
*/
#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 1e9 + 7;
const ll seed = 12289;
const double eps = 1e-6;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll N = 2e5 + 10;
struct node {
ll fi, se;
} arr[N];
bool cmp(node a, node b)
{
if (a.fi == b.fi)
return a.se > b.se;
return a.fi > b.fi;
}
ll pre[N], n, m;
ll get(ll x)
{
ll l = 1, r = m, ans = 0;
while (l <= r) {
ll mid = (l + r) / 2;
if (arr[mid].fi >= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
int main() //ll
{
ll _;
scanf("%lld", &_); //ll
while (_--) {
scanf("%lld %lld", &n, &m);
for (ll i = 1; i <= m; i++) {
scanf("%lld%lld", &arr[i].fi, &arr[i].se);
}
sort(arr + 1, arr + 1 + m, cmp);
for (ll i = 1; i <= m; i++) {
pre[i] = pre[i - 1] + arr[i].fi;
}
ll ans = 0;
for (ll i = 1; i <= m; i++) {
ll tmp = get(arr[i].se);
tmp = min(tmp, n);
if (tmp >= i) {
ans = max(ans, pre[tmp] + (n - tmp) * arr[i].se);
} else {
if (n - tmp)
ans = max(ans, pre[tmp] + arr[i].fi + (n - tmp - 1) * arr[i].se);
else
ans = max(ans, pre[tmp]);
}
}
printf("%lld\n", ans);
}
return 0;
}
/*
10000
3 4
4 1
5 1
1 5
4 3
*/