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;
}
posted @ 2022-05-21 23:37  落花月朦胧  阅读(110)  评论(5编辑  收藏  举报