[Luogu] CF1379C Choosing flowers
阿新 • • 發佈:2020-11-21
Description
有\(m\)種物品,每種物品有無限個,你可以購買\(n\)個物品。
對於第\(i\)種物品:第一次買時的貢獻是\(a_i\) ,接下來每購買一個的貢獻都是\(b_i\)。即當你買了\(x_i\)個第\(i\)種物品時,貢獻是 \(a_i+b_i \times (x_i-1)\)
現在要你求出最大貢獻。
Solution
這道題有一個重要的性質,就是我們要麼不買\(b_i\),要麼只買一種\(b_i\)。證明:不妨設買第\(i\)種物品\(t_i\)個和第\(j\)種物品\(t_j\)個,且\(b_i\ge{b_j}\)。假設\(t_i>1,t_j>1\)
還有一個性質,就是如果我們選擇買一種\(b_i\),那麼\(\le{b_i}\)的\(a_j\)必定不選,\(>b_i\)的\(a_j\)必定要選。
這樣我們就可以二分了(就是過載小於號\(lower\_bound\))
Code
#include <bits/stdc++.h> using namespace std; #define ll long long int t, n, m; ll res, s[100005]; struct node { int a, b; }obj[100005]; int read() { int x = 0, fl = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();} while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();} return x * fl; } bool operator < (const node &a, const node &b) { return a.a > b.a; } int main() { t = read(); while (t -- ) { n = read(); m = read(); for (int i = 1; i <= m; i ++ ) { obj[i].a = read(); obj[i].b = read(); } sort(obj + 1, obj + m + 1); for (int i = 1; i <= m; i ++ ) s[i] = s[i - 1] + (ll)obj[i].a; res = s[min(n, m)]; for (int i = 1; i <= m; i ++ ) { int pos = lower_bound(obj + 1, obj + m + 1, (node){obj[i].b, 0}) - obj - 1; if (pos < i && pos <= n - 1) res = max(res, s[pos] + obj[i].a + 1ll * (n - pos - 1) * obj[i].b); else if (pos <= n) res = max(res, s[pos] + 1ll * (n - pos) * obj[i].b); } printf("%lld\n", res); } return 0; }