CF1676E Eating Queries 题解
题意
给出 \(n\) 个数, 每个数都有一个权值 \(a_i\)。
让你选择尽可能少的数,使这些数的和大于等于 \(x\)。 这种询问是多次且独立的。
解
发现要求个数少,权值大,于是想到贪心,可以从小到大排序。
本题的一个关键是对时间复杂度的规划。
排完序之后,我们要实现的是 2 个点
- 获得一个区间和
- 找到一个位置,让这个区间和大于等于 \(x\)
根据我们学习的算法,可以轻松的想到第一个实现的点要使用前缀和来进行优化,而第二个要实现的点则需呀用二分查找来进行优化,加上这两个优化之后,本题就可以轻松 \(\texttt{AC}\) 了。
二分你可以手写,也可以用 STL 中的 lower_bound
。
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
constexpr int inf = INT_MAX;
constexpr i64 lnf = LONG_LONG_MAX;
int a[1000000];
void solve() {
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + n + 1, greater<int>());
for (int i = 1; i <= n; i++) {
a[i] += a[i - 1];
}
while (q--) {
int x; cin >> x;
int ans = lower_bound(a + 1, a + n + 1, x) - a;
if (ans > n) {
ans = -1;
}
cout << ans << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}