Eating Queries
题目描述
Timur has n candies. The i-th candy has a quantity of sugar equal to ai. So, by eating the i-th candy, Timur consumes a quantity of sugar equal to ai.
Timur will ask you q queries regarding his candies. For the j-th query you have to answer what is the minimum number of candies he needs to eat in order to reach a quantity of sugar greater than or equal to xj or print -1 if it's not possible to obtain such a quantity. In other words, you should print the minimum possible k such that after eating k candies, Timur consumes a quantity of sugar of at least xj or say that no possible k exists. Note that he can't eat the same candy twice and queries are independent of each other (Timur can use the same candy in different queries).
输入描述:
The first line of input contains a single integer t (1≤t≤1000) — the number of test cases. The description of test cases follows.
The first line contains 2 integers n and q (1≤n,q≤1.5⋅10^5) — the number of candies Timur has and the number of queries you have to print an answer for respectively. The second line contains n integers a1,a2,…,an (1≤ai≤104) — the quantity of sugar in each of the candies respectively. Then q lines follow. Each of the next q lines contains a single integer xj (1≤xj≤2⋅10^9) – the quantity Timur wants to reach for the given query. It is guaranteed that the sum of n and the sum of q over all test cases do not exceed 1.5⋅105.
输出描述:
Output For each test case output q lines. For the j-th line output the number of candies Timur needs to eat in order to reach a quantity of sugar greater than or equal to xj or print -1 if it's not possible to obtain such a quantity.
输入
3
8 7
4 3 3 1 1 4 5 9
1
10
50
14
15
22
30
4 1
1 2 3 4
3
1 2
5
4
6
输出
1
2
-1
2
3
4
8
1
1
-1
题目大意及解题思路
大意:
帖木儿有n颗糖果。第i颗糖果的糖量等于ai。因此,帖木儿通过吃第i颗糖,消耗了等于ai的糖量。
帖木儿会问你关于他的糖果的问题。对于第j个查询,你必须回答他需要吃多少糖果才能达到大于或等于xj的糖量,或者如果无法获得这样的数量,则打印-1。换句话说,你应该打印出可能的最小k,这样帖木儿在吃了k颗糖果后,会消耗至少xj的糖,或者说不存在可能的k。请注意,他不能吃两次相同的糖果,并且查询是相互独立的(帖木儿可以在不同的查询中使用相同的糖果)。
思路:
题目意思并不难理解,就是让我们找到最少的糖的颗数,使得他们的甜度之和>=给出的查询值,很容易想到先将数组排序,这里我使用降序排序,然后去找符合题目的颗数,看到数据很大,所以可以想到用二分查找来解决。
重点来了,如果这样来解决,我们还需要计算甜度的和,o(n)的时间复杂度,实际上是会超时的。第一次就卡到了这里,仔细观察数据才发现需要处理一下求和。 那就得使用我们熟知的前缀和算法了,将前缀和预处理出来,就不用每次去求和,降低了整个算法的时间复杂度。同时还要注意,前缀和一定要在排完序之后去求,没排序前的对我们没有意义!!
AC代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;
const int N = 2e5 + 5;
int a[N], s[N];//预处理前缀和,降低时间复杂度
int n, m, target;
bool cmp(int a, int b)
{
return a > b;
}
signed main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i <= n; i++)
s[i] = s[i - 1] + a[i];
while (m--)
{
cin >> target;
int l = 0, r = n;
while (l < r)
{
int mid = (l + r) / 2;
if (s[mid] >= target)
{
r = mid;
}
else
{
l = mid + 1;
}
}
if (s[l] < target) cout << -1 << endl;
else cout << l << endl;
}
}
return 0;
}