题面
B. Lunar New Year and Food Ordering
Lunar New Year is approaching, and Bob is planning to go for a famous restaurant — “Alice’s”.
The restaurant “Alice’s” serves n kinds of food. The cost for the i-th kind is always ci. Initially, the restaurant has enough ingredients for serving exactly ai dishes of the i-th kind. In the New Year’s Eve, m customers will visit Alice’s one after another and the j-th customer will order dj dishes of the tj-th kind of food. The (i+1)-st customer will only come after the i-th customer is completely served.
Suppose there are ri dishes of the i-th kind remaining (initially ri=ai). When a customer orders 1 dish of the i-th kind, the following principles will be processed.
If ri>0, the customer will be served exactly 1 dish of the i-th kind. The cost for the dish is ci. Meanwhile, ri will be reduced by 1.
Otherwise, the customer will be served 1 dish of the cheapest available kind of food if there are any. If there are multiple cheapest kinds of food, the one with the smallest index among the cheapest will be served. The cost will be the cost for the dish served and the remain for the corresponding dish will be reduced by 1.
If there are no more dishes at all, the customer will leave angrily. Therefore, no matter how many dishes are served previously, the cost for the customer is 0.
If the customer doesn’t leave after the dj dishes are served, the cost for the customer will be the sum of the cost for these dj dishes.
Please determine the total cost for each of the m customers.
Input
The first line contains two integers n and m (1≤n,m≤105), representing the number of different kinds of food and the number of customers, respectively.
The second line contains n positive integers a1,a2,…,an (1≤ai≤107), where ai denotes the initial remain of the i-th kind of dishes.
The third line contains n positive integers c1,c2,…,cn (1≤ci≤106), where ci denotes the cost of one dish of the i-th kind.
The following m lines describe the orders of the m customers respectively. The j-th line contains two positive integers tj and dj (1≤tj≤n, 1≤dj≤107), representing the kind of food and the number of dishes the j-th customer orders, respectively.
Output
Print m lines. In the j-th line print the cost for the j-th customer.
Examples
input
8 5
8 6 2 1 4 5 7 5
6 3 3 2 6 2 3 2
2 8
1 4
4 7
3 4
6 10
output
22
24
14
10
39
input
6 6
6 6 6 6 6 6
6 66 666 6666 66666 666666
1 6
2 6
3 6
4 6
5 6
6 66
output
36
396
3996
39996
399996
0
input
6 6
6 6 6 6 6 6
6 66 666 6666 66666 666666
1 6
2 13
3 6
4 11
5 6
6 6
output
36
11058
99996
4333326
0
0
Note
In the first sample, 5 customers will be served as follows.
- Customer 1 will be served 6 dishes of the 2-nd kind, 1 dish of the 4-th kind, and 1 dish of the 6-th kind. The cost is 6⋅3+1⋅2+1⋅2=22. The remain of the 8 kinds of food will be {8,0,2,0,4,4,7,5}.
- Customer 2 will be served 4 dishes of the 1-st kind. The cost is 4⋅6=24. The remain will be {4,0,2,0,4,4,7,5}.
- Customer 3 will be served 4 dishes of the 6-th kind, 3 dishes of the 8-th kind. The cost is 4⋅2+3⋅2=14. The remain will be {4,0,2,0,4,0,7,2}.
- Customer 4 will be served 2 dishes of the 3-rd kind, 2 dishes of the 8-th kind. The cost is 2⋅3+2⋅2=10. The remain will be {4,0,0,0,4,0,7,0}.
- Customer 5 will be served 7 dishes of the 7-th kind, 3 dishes of the 1-st kind. The cost is 7⋅3+3⋅6=39. The remain will be {1,0,0,0,4,0,0,0}.
In the second sample, each customer is served what they order except the last one, who leaves angrily without paying. For example, the second customer is served 6 dishes of the second kind, so the cost is 66⋅6=396.
In the third sample, some customers may not be served what they order. For example, the second customer is served 6 dishes of the second kind, 6 of the third and 1 of the fourth, so the cost is 66⋅6+666⋅6+6666⋅1=11058.
time limit per test | memory limit per test | input | output |
---|---|---|---|
2 seconds | 256 megabytes | standard input | standard output |
题目大意
对于每一道菜,都有一个数量 a i a_i ai和一个成本 c i c_i ci。对于每个客人(有顺序的),都会购买顺序为 t i t_i ti的菜 d i d_i di份。每个客人都遵循以下的行为:
- 若 d i ≥ a i d_i \ge a_i di≥ai,客人直接购买,而且这一份菜的数量会变少。
- 若 d i < a i d_i < a_i di<ai,客人会买光顺序为 t i t_i ti的菜,剩下的菜会按菜的便宜顺序购买.
- 若按便宜顺序购买后,依然不能满足客人的需求,客人便会离去,此时客人的成本为0,而客人一样会带走他所点的菜,即使他没有被满足。
任务就是按顺序输出每个客人的成本。
题目分析
其实就是一道模拟题,直接模拟会T,所以要进行一定的优化。T的主要原因在于,对于 n n n道菜 m m m个客人,当每个客人都不能满足时,便会从 1 1 1到 n n n遍历一遍,造成时间复杂度为 O ( n m ) O(nm) O(nm),所以我们要避免这种遍历
留意到,当便宜的菜购买完时,可以剔除掉这个菜,下次不用再次判断。而且,最便宜的肯定先剔除,所以这其实就是一个优先队列,便宜的就先出列。
其实一开始我是用sort再加入到队列中的,发现这样的时间更少……原理一时不懂。
代码
优先队列:
#include <cstdio>
#include <queue>
using namespace std;
const int Max = 1e5 + 7;
typedef struct Node{
int index, cost;
bool operator < (const Node &a) const{
return cost > a.cost;
}
}node;
typedef long long ll;
int n, m;
ll have[Max];
ll cost[Max];
priority_queue<node> que;
ll sum = 0;
void solve(ll index, ll need){
if(!sum){
printf("0\n");
return;
}
if(have[index] >= need){
have[index] -= need;
sum -= need;
printf("%lld\n", cost[index] * need);
return;
}else{
ll pay = 0;
pay += have[index] * cost[index];
need -= have[index];
sum -= have[index];
have[index] = 0;
while(que.size()){
node a = que.top();
index = a.index;
if(have[index] >= need){
have[index] -= need;
sum -= need;
printf("%lld\n", pay + cost[index] * need);
if(!have[index])
que.pop();
return ;
}else{
pay += have[index] * cost[index];
need -= have[index];
sum -= have[index];
have[index] = 0;
que.pop();
}
}
printf("0\n");
}
}
int main(int argc, char const *argv[]) {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++){
scanf("%d", &have[i]);
sum += have[i];
}
for(int i = 0; i < n; i++){
scanf("%d", &cost[i]);
node t;
t.cost = cost[i];
t.index = i;
que.push(t);
}
for(int j = 0; j < m; j++){
ll t, d;
scanf("%lld%lld", &t, &d);
solve(t - 1, d);
}
return 0;
}
普通队列
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int Max = 1e5 + 4;
typedef struct {
int cost, index;
}node;
typedef long long ll;
int n, m;
node ac[Max];
ll have[Max];
ll cost[Max];
queue<node> que;
ll sum;
bool cmp(node a, node b){
return a.cost < b.cost;
}
void solve(ll index, ll need){
if(!sum){
printf("0\n");
return ;
}
if(have[index] >= need){
have[index] -= need;
sum -= need;
printf("%lld\n", need * cost[index]);
return ;
}else{
ll pay = 0;
need -= have[index];
pay += have[index] * cost[index];
have[index] = 0;
while(que.size()){
node now = que.front();
index = now.index;
if(have[index] >= need){
have[index] -= need;
sum -= need;
printf("%lld\n", pay + need * cost[index]);
if(have[index] == 0)
que.pop();
return ;
}else{
need -= have[index];
sum -= have[index];
pay += have[index] * cost[index];
have[index] = 0;
que.pop();
}
}
}
printf("0\n");
}
int main(int argc, char const *argv[]) {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++){
scanf("%lld", &have[i]);
sum += have[i];
}
for(int i = 0; i < n; i++){
scanf("%lld", &cost[i]);
ac[i].cost = cost[i];
ac[i].index = i;
}
sort(ac, ac + n, cmp);
for(int i = 0; i < n; i++){
que.push(ac[i]);
}
for(int j = 0; j < m; j++){
ll t, d;
scanf("%lld%lld", &t, &d);
solve(t -1 , d);
}
return 0;
}