2020牛客暑期多校训练营(第八场)K - Kabaleo Lite 题解

[原题传送门]

Tired of boring WFH (work from home), Apollo decided to open a fast food restaurant, called Kabaleo   Lite \textbf{Kabaleo Lite} Kabaleo Lite.
The restaurant serves n kinds of food, numbered from 1 to n. The profit for the i-th kind of food is a i a_i ai. Profit may be negative because it uses expensive ingredients. On the first day, Apollo prepared b i b_i bi dishes of the i i i-th kind of food.
The peculiarity of Apollo’s restaurant is the procedure of ordering food. For each visitor Apollo himself chooses a set of dishes that this visitor will receive. When doing so, Apollo is guided by the following rules:
every visitor should receive at least one dish.
each visitor should receive continuous kinds of food started from the first food. And the visitor will receive exactly 1 dish for each kind of food. For example, a visitor may receive 1 dish of the 1st kind of food, 1 dish of the 2nd kind of food, 1 dish of the 3rd kind of food.
What’s the maximum number of visitors Apollo can feed? And he wants to know the maximum possible profits he can earn to have the maximum of visitors.

输入描述:

The first line of the input gives the number of test case, T ( 1 ≤ T ≤ 10 ) \mathbf{T} (1 \leq \mathbf{T} \leq 10) T(1T10) test cases follow.
Each test case begins with a line containing one integers n ( 1 ≤ n ≤ 1 0 5 ) n (1 \le n \le 10^5) n(1n105), representing the number of different kinds of food.
The second line contains n space-separated numbers a i ( − 1 0 9 ≤ a i ≤ 1 0 9 ) a_i(-10^9 \le a_i \le 10^9) ai(109ai109), where a i a_i ai denotes the profit of one dish of the i-th kind.
The third line contains n space-separated numbers b i ( 1 ≤ b i ≤ 1 0 5 ) b_i(1 \le b_i \le 10^5) bi(1bi105), where b i b_i bi denotes the number of the i-th kind of dishes.

输出描述:

For each test case, output one line containing ‘ ‘ C a s e   # x :   y   z ′ ′ ``Case\ \#x:\ y\ z'' Case #x: y z, where x x x is the test case number (starting from 1), y y y is the maximum number of visitors, and z z z is the maximum possible profits.

样例

input
2
3
2 -1 3
3 2 1
4
3 -2 3 -1
4 2 1 2
output
Case #1: 3 8
Case #2: 4 13
Note

For test case 1, the maximum number of visitors is 3, one of a possible solution is:
The first visitor received food 1, the profit is 2.
The second visitor received food 1, the profit is 2.
The third visitor received food 1 + food 2 + food 3, the profit is 2 + (-1) + 3.

my Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2020-08-03 13:14:58
 * @LastEditTime: 2020-08-03 20:04:51
 */
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>

#define ll long long
#define db double
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define rep(l, a, b) for (ll l = a; l < b; ++l)
#define per(l, a, b) for (ll l = a; l >= b; --l)
#define debug(a) cout << '#' << a << '#' << endl

using namespace std;
bool fi = true;
const unsigned long long MOD = 1e9 + 7;

ll gcd(ll a, ll b) { return (b == 0 ? a : gcd(b, a % b)); }

// 打印大数
void print(__int128_t x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}

struct valsq {
	// 由于利润和使用__int128_t
	// 所以用于计算利润和的数据也要使用__int128_t
    __int128_t preval;
    ll index;
};

// 个体利润
ll val[100005];
// 个体个数
ll num[100005];
// 前i道菜的最小个数
ll prenum[100005];
// 利润和前缀
ll pre[100005];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    ll t;
    scanf("%lld", &t);
    ll _case = 1;
    while (t--) {
        vector<valsq> a;
        ll n, ansnum = 0;
        // long long存放利润和会溢出
        // 需要使用__int128_t
        __int128_t ansval = 0;
        scanf("%lld", &n);
        rep(i, 0, n) {
            scanf("%lld", &val[i]);
            pre[i] = val[i] + (i == 0 ? 0 : pre[i - 1]);
            valsq aa;
            aa.preval = pre[i];
            aa.index = i;
            a.push_back(aa);
        }
        ll minprenum = MOD;
        rep(i, 0, n) {
            scanf("%lld", &num[i]);
            minprenum = min(minprenum, num[i]);
            // 记录到从第1到菜到第i道菜最多可以满足的客人数
            prenum[i] = minprenum;
        }
        // 贪心做法
        // 将菜品以利润从高到低排序
        sort(a.begin(), a.end(),
             [](valsq &x, valsq &y) { return x.preval > y.preval; });
      	// times记录上一道菜品计入利润和后共招待多少个客人
        ll times = 0;
        for (ll ii = 0; ii < n; ii++) {
            // 若当前最多可以满足的客人大于times
            // 将利润计入利润和ansval
            // 维护times
            if (prenum[a[ii].index] > times) {
                ansval +=
                    (__int128_t)(a[ii].preval * (prenum[a[ii].index] - times));
                times = prenum[a[ii].index];
            }
        }
        printf("Case #%lld: %lld ", _case++, times);
        print(ansval);
        printf("\n");
    }
}

没想到会数据超 l o n g long long l o n g long long T ^ T
了解了一波大数的使用和打印
学到了 这就去和神犇的签到题对线

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值