1. 程式人生 > 實用技巧 >【Codeforces】#657 C.Choosing flowers 列舉 二分

【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
*/