牛客多校(2020第八场) K - Kabaleo Lite
参考:https://www.cnblogs.com/lilibuxiangtle/p/13427959.html
题目描述
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 aia_iai. Profit may be negative because it uses expensive ingredients. On the first day, Apollo prepared bib_ibi dishes of the 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:
The restaurant serves n kinds of food, numbered from 1 to n. The profit for the i-th kind of food is aia_iai. Profit may be negative because it uses expensive ingredients. On the first day, Apollo prepared bib_ibi dishes of the 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.
输入描述:
The first line of the input gives the number of test case, T\mathbf{T}T (1≤T≤101 \leq \mathbf{T} \leq 101≤T≤10). T\mathbf{T}T test cases follow.
Each test case begins with a line containing one integers n (1≤n≤1051 \le n \le 10^51≤n≤105), representing the number of different kinds of food.
The second line contains n space-separated numbers aia_iai (−109≤ai≤109-10^9 \le a_i \le 10^9−109≤ai≤109), where aia_iai denotes the profit of one dish of the i-th kind.
The third line contains n space-separated numbers bib_ibi (1≤bi≤1051 \le b_i \le 10^51≤bi≤105), where bib_ibi denotes the number of the i-th kind of dishes.
输出描述:
For each test case, output one line containing ‘‘Case #x: y z′′``Case\ \#x:\ y\ z''‘‘Case #x: y z′′, where x is the test case number (starting from 1), y is the maximum number of visitors, and z is the maximum possible profits.
示例1
输入
2 3 2 -1 3 3 2 1 4 3 -2 3 -1 4 2 1 2
输出
Case #1: 3 8 Case #2: 4 13
说明
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.
题解:
题目大意:
- 有n种菜,每种菜的数量为bi,每个菜的盈利为ai
- 每个顾客必须是从第1种菜开始吃,连续地吃,每种吃一个
- 保证顾客最多的情况下,盈利最大
题解:
- 最大顾客数量就是b1,然后求盈利的前缀和,从大到小取就好(可以使用优先队列protiry_queue)
- 结果会超出long long,可以使用__int128,或者把大数拆开存储(拆成俩个long long)
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 typedef __int128 ll;
5 const ll N = 1e5 + 5;
6 ll a[N],b[N];
7 ll dp[N];//dp存储价钱的前缀和
8 ll n,t;
9
10 #define P pair<ll, pair<ll, ll>> //第一个存dp[i], 第二个存数量, 第三个存菜的下标(第几道菜)
11 priority_queue <P> que;
12
13 inline int read(){
14 int x=0,f=1;
15 char ch=getchar();
16 while(ch<'0'||ch>'9'){
17 if(ch=='-')
18 f=-1;
19 ch=getchar();
20 }
21 while(ch>='0'&&ch<='9'){
22 x=x*10+ch-'0';
23 ch=getchar();
24 }
25 return x*f;
26 }
27
28 inline void print(__int128 x){
29 if(x<0){
30 putchar('-');
31 x=-x;
32 }
33 if(x>9)
34 print(x/10);
35 putchar(x%10+'0');
36 }
37
38 ll solve() {
39 ll res = 0;
40 ll pos_now = n, now_food_num = 0;
41
42 while (!que.empty()) {
43 ll max_price = que.top().first; //最大利润
44 ll food_num = que.top().second.first; //菜品数量
45 ll pos = que.top().second.second; //菜品名
46 que.pop();
47 if (pos_now <= pos || food_num <= now_food_num) { //当该菜品位置位于pos_now之后则不可上菜
48 continue;
49 }
50
51 res += (food_num - now_food_num) * max_price; //(需要减去上次用的菜品,因为其数量的价值上一次已经算过了)
52 now_food_num = food_num; //更新上一次用去的菜品数量
53 pos_now = pos; //更新菜品位置
54 }
55 return res;
56 }
57 int main() {
58 /* ios::sync_with_stdio(false);
59 cin.tie(0); cin.tie(0); */
60 t = read();
61 for(ll i = 1; i <= t; i++) {
62 n = read();
63 for(ll j = 0; j < n; j++) {
64 a[j] = read();
65 if (!j) dp[j] = a[j]; //dp存储价钱的前缀和
66 else dp[j] = dp[j-1] + a[j];
67 }
68
69 for(ll j = 0; j < n; j++) {
70 b[j] = read();
71 }
72
73 ll bb = b[0];
74 for (ll j = 0; j < n; j++) {
75 bb = min(bb, b[j]); //因为当前面的菜没了的时候,后面的菜也相当于没有,所以一直更新前方菜品的最小值
76 que.push({dp[j], {bb, j}});
77 }
78
79 ll ans = solve();
80 cout << "Case #";
81 print(i);
82 cout << ": ";
83 print(b[0]);
84 cout << " ";
85 print(ans);
86 puts("");
87 }
88 /* clock_t end = clock();
89 cout << end - start << "\n"; */
90 return 0;
91 }
92 /*
93 2
94 6
95 1 1 1 1 1 1
96 8 3 2 1 9 3
97 6
98 2 -1 -3 4 5 -5
99 10 9 8 7 6 5
100 */

浙公网安备 33010602011771号