codeforces 练习 Mr. Perfectly Fine

104 阅读4分钟

C. Mr. Perfectly Fine

题目描述

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.

输入

6
4
2 00
3 10
4 01
4 00
5
3 01
3 01
5 01
2 10
9 10
1
5 11
3
9 11
8 01
7 10
6
4 01
6 01
7 01
8 00
9 01
1 00
4
8 00
9 10
9 11
8 11

输出

7
5
5
9
-1
8

题目大意及解题思路

大意:
维克多想成为“完美先生”。为此,他需要掌握一定的技能。更确切地说,他有两项技能需要掌握。 维克多有n本书。我读这本书花了他几分钟的时间,并将给他一些(可能没有)所需的两项技能,用长度为2的二进制字符串表示。维克多获得这两项技能所需的最短时间是多少? 输入由多个测试用例组成。第一行包含一个整数(1≤t≤1000)——测试用例的数量。测试用例的描述如下。 每个测试用例的第一行包含一个整数n(1≤n≤2∙10^5)——可用书籍的数量。接着是n行。第i行包含一个正整数m_i(1≤mi≤2∙10^5)和一个长度为2的二进制字符串,其中如果读书i获得Victor skill 1,则s_i1=1,否则s_i1=0,如果读书i获取Victor skill2,则s_i2=1,否则s_i2=0。对于每个测试用例,输出一个整数,表示Victor获得所需技能所需的最小分钟数,如果在阅读了大量书籍后无法获得这两项技能,则输出−1。
思路:
这是一道字符串处理的题,就是让我们在给定的些许两位字符串中,看能否找到两位1?,并且每个字符串有对应的时间m,要求m最小。这里我用结构体来存每本书的信息,包括时间m,和字符串s。将所有字符串按字典序排序,相同的再按时间升序排序。对于每个两位二进制字符串,一共就4种情况(11,10,01,00),而且,我们排完序后就是这样的顺序。然后我们依次找,看是否有前三种字符。
需要注意,不能找到11就结束,因为可能10+01的时间更少。下面就是最后的输出判断。

    if (f1 && f2 && sum1 != 0) cout << min(sum1, sum) << endl;
    else if (f1 && f2 && sum1 == 0) cout <<  sum << endl;
    else if (sum1 != 0) cout << sum1 << endl;
    else cout << "-1" << endl;

AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;

const int N = 200010;
int a[N], s[N];//预处理前缀和,降低时间复杂度

struct bo {
    int m;
    string s;
}book[N];
bool cmp(bo a,bo b)
{
    if (a.s != b.s)
    {
        return a.s > b.s;
    }
    else
    {
        return a.m < b.m;
    }
}
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        for (int i = 0; i < n; i++)
        {
            cin >> book[i].m >> book[i].s;
        }
        sort(book, book + n,cmp);
        int sum1 = 0;
        bool f1= false, f2 = false;

        if (book[0].s == "11")
        {
            sum1 += book[0].m;
        }
        int sum = 0;
        for (int i = 0; i < n; i++)
        {
            if (book[i].s == "10") 
            {
                sum += book[i].m;
                f1 = true;
                break;
            }
        }

        for (int i = 0; i < n; i++)
        {
            if (book[i].s == "01")
            {
                sum += book[i].m;
                f2 = true;
                break;
            }
        }
        if (f1 && f2 && sum1 != 0) cout << min(sum1, sum) << endl;
        else if (f1 && f2 && sum1 == 0) cout <<  sum << endl;
        else if (sum1 != 0) cout << sum1 << endl;
        else cout << "-1" << endl;
    }
    return 0;
}