“战疫杯”大学生程序设计在线邀请赛4核酸排队
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“战疫杯”大学生程序设计在线邀请赛4核酸排队相关的知识,希望对你有一定的参考价值。
核酸排队
题目链接:
https://vj.wangyaqii.top/problem/1024
在疫情到来的时候,做核酸成了大多数同学们的日常。做核酸也是需要时间的,而且在一个核酸检测点做核酸的人数往往很多,等待时间有时候会比较长。
在一个核酸检测点基本都安排有两个队列(默认两个队列的长度都为无限大):
- 扫码队列:在该队列中,我们等待志愿者扫码录入核酸检测信息,志愿者每扫一个同学的码需要 x x x单位时间。
- 核酸队列:在该队列中,我们等待医生为我们做核酸,每个同学做核酸需要 y y y单位时间。
一位同学做核酸的过程可以认为是先到达扫码队列等待志愿者扫码录入信息,录入信息之后到达核酸队列等待做核酸。一个志愿者一次只能处理一个同学的扫码,一个医生一次只能对一位同学进行核酸检测。
小王深深体会到了医生们的辛苦,他希望通过计算同学们等待做核酸的时间,以此平衡好同学们做核酸、学习和生活的时间。
假设核酸检测点只有一个志愿者和一个医生。已知有 n n n个同学,第 i i i个同学到达核酸检测点(即到达扫码队列)的时间为 t i t_i ti(数据保证到达扫码队列的时间是升序的,且各不相同),求编程计算第 i i i个同学做核酸耗费的时间 w i w_i wi。
本题认为耗费时间为从到达扫码队列到完成做核酸的时间。
input
一共三行。
第一行为一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n(1 \\leq n \\leq 10^5) n(1≤n≤105)。
第二行为两个整数 x , y ( 1 ≤ x , y ≤ 1 0 5 ) x, y (1 \\leq x, y \\leq 10^5) x,y(1≤x,y≤105)
第三行为 n n n个整数 t 1 , t 2 , t 3 , . . . , t n − 1 , t n ( 1 ≤ t i ≤ 1 0 9 ) t_1,t_2,t_3,...,t_n - 1,t_n(1 \\leq t_i \\leq 10^9) t1,t2,t3,...,tn−1,tn(1≤ti≤109)
output
在一行输出 n n n个核酸检测等待时间 w 1 , w 2 , w 3 , . . . , w n w_1, w_2, w_3,...,w_n w1,w2,w3,...,wn
input
3
2 3
3 5 6
output
5 6 8
标程
不开long long见祖宗
比较详细地解析思路:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
int n, x, y;
cin >> n >> x >> y;
vector<ll> t(n + 1);
for(int i = 1; i <= n; i++)
cin >> t[i];
// 扫码队列
// t[] : 到达扫码队列的时间
// start[] : 开始扫码的时间
// end[] : 结束扫码的时间
vector<ll> start(n + 1), end(n + 1);
for(int i = 1; i <= n; i++)
start[i] = max(end[i - 1], t[i]);// 开始扫码的时间
end[i] = start[i] + x;//结束扫码的时间
// 核酸队列
// tmp[] = end[] : 到达核酸队列的时间
// start[] : 开始做核酸的时间
// end[] :做完核酸的时间
// 重复上述思路即可
vector<ll> tmp = end;
for(int i = 1; i <= n; i++)
start[i] = max(end[i - 1], tmp[i]); // 开始做核酸的时间
end[i] = start[i] + y; // 做完核酸的时间
// 核酸队列结束时间-扫码队列到达时间
for(int i = 1; i <= n; i++)
cout << end[i] - t[i] << " \\n"[i == n];
int main()
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
对上述代码进行合并
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 5;
void solve()
ll n, x, y;
cin >> n >> x >> y;
// a[] : 扫完码的时间
// b[] : 做完核酸的时间
vector<ll> t(n + 1), a(n + 1), b(n + 1);
for(int i = 1; i <= n; i++)
cin >> t[i]; // 到达扫码队列的时间
// 扫完码(到达核酸队列)的时间 = max(前一个人扫完码的时间 + x,本人到达扫码队列就扫码的情况下 扫完码的时间)
a[i] = max(a[i - 1] + x, t[i] + x);
// 做完核酸的时间 = max(前一个人做完核酸的时间 + y, 本人到达核酸队列就做核酸的情况下 做完核酸的时间)
b[i] = max(b[i - 1] + y, a[i] + y);
for(int i = 1; i <= n; i++)
cout << b[i] - t[i] << " \\n"[i == n];
int main()
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
思考
1
如果核酸队列的长度限制为 k k k,即当核酸队列满了,扫码队列中扫码便不再进行,耗费时间怎么样?
不影响答案
分情况考虑:
-
x ≥ y x \\geq y x≥y (核酸做的比扫码快),相当于核酸队列一直不会满,可以等价于核酸队列无长度限制(原问题)
-
x < y x \\lt y x<y (核酸做的比扫码慢),核酸队列可能会满,扫码队列就会产生等待
但是只要核酸队列不满,扫码队列中的人就会到核酸队列中补充。
无论是在扫码队列中等待还是在核酸队列中等待,都是在等待,时间一样在消耗,时间消耗的效果是一样的,唯一不一样的是等待的位置不一样。
2
如果再加上 每个人扫码和做核酸时间不一样 (即有不同的
x
i
,
y
i
x_i,y_i
xi,yi)的条件,即不同的人有不同的x
和y
,结果该怎么样?
大家可以思考一下
需要特判一下 每个人扫完码 的时间,因为扫码开始的时间受核酸队列长度的影响,核酸队列满的话,扫码便不再进行(后一个人要扫码了,但是前面核酸队列满了,所以不再进行扫码直到核酸队列不满)。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
int n, k;
cin >> n >> k;
vector<ll> t(n + 1), x(t), y(t);
for(int i = 1; i <= n; i++)
cin >> t[i];
for(int i = 1; i <= n; i++)
cin >> x[i];
for(int i = 1; i <= n; i++)
cin >> y[i];
// b[] : 扫完码的时间
// c[] : 做完核酸的时间
vector<ll> b(n + 1), c(n + 1);
for(int i = 1; i <= n; i++)
b[i] = t[i];
b[i] = max(b[i], b[i - 1]); // 前一个人 扫完码 和 本人到达扫码队列 取 max
// 特殊处理扫码完成的时间(到达核酸队列的时间)
if(i - k >= 0)
b[i] = max(b[i], c[i - k]);
// 开始扫码
b[i] += x[i];
c[i] = b[i];
c[i] = max(c[i], c[i - 1]);
c[i] += y[i];
for(int i = 1; i <= n; i++)
cout << c[i] - t[i] << " \\n"[i == n];
int main()
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
以上是关于“战疫杯”大学生程序设计在线邀请赛4核酸排队的主要内容,如果未能解决你的问题,请参考以下文章