蓝桥杯真题 外卖店优先级

考点

模拟、优化

(我看了好几个题解都把店家和时间挨个遍历了一遍,这样会超时)

(我的代码还有一些问题,现在只能拿60分,但是时间是在范围内的,之后有空再慢慢debug吧,这里做个记录)

 

题目描述

“饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。

每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。

如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。

给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中。

输入格式

第一行包含 3 个整数 N、M 和 T。

以下 M 行每行包含两个整数 ts 和 id,表示 ts 时刻编号 id 的外卖店收到 一个订单。

输出格式

输出一个整数代表答案。

样例输入

2 6 6 1 1 5 2 3 1 6 2 2 1 6 2

样例输出

1

样例解释

6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。

评测用例规模与约定

对于 80% 的评测用例,1≤ N,M,T ≤10000。 对于所有评测用例,1≤ N,M,T ≤100000,1≤ts≤T,1≤id ≤ N。

时间限制:1.0s

内存限制:512.0MB

 

思路:

我们要模拟这个优先级改变的过程,就要看每一步发生改变的地方在哪里

以时间来看,先看有没有订单,如果有,则有订单的店要加2*新增订单数个优先级;如果没有就直接看下一时刻。

但对于没有订单的点,如果全部遍历一边就太耗时了。所以我们用Last[i]记录第i家店上一次来订单的时间,这样在计算新时刻时,就可以直接用j-k来判断要减的数

对于每一时刻的优先级更新后,要判断是否可以进入优先缓冲

在所有有订单的时刻遍历完毕后,要对t时刻再次判断每个店的last[i]是否是t,如果不是,要对优先级进行更新(减)。

最后遍历缓冲序列得到结果

 

代码

 1 import java.util.ArrayList;
 2 import java.util.Collections;
 3 import java.util.List;
 4 import java.util.Scanner;
 5 
 6 public class Main {
 7     public static void main(String args[]) {
 8         Scanner in = new Scanner(System.in);
 9         int n = in.nextInt();
10         int m = in.nextInt();
11         int t = in.nextInt();
12         List<Integer>[] arr = new ArrayList[t + 1];// 存储每时刻的订单
13         int[] last = new int[n + 1];// 每个店上一次计算出现订单的时刻(注意这里是计算,每次会被刷新)
14         int[] score = new int[n + 1];// 记录每个店子的优先级数
15         boolean[] level = new boolean[n + 1];// 是否放入优先缓存
16         // 初始化!不然会报错Cannot invoke "java.util.List.add(Object)" because "arr[ts]" is null
17         for (int i = 0; i < t + 1; i++) {
18             arr[i] = new ArrayList();
19         }
20         // 输入数据
21         for (int i = 0; i < m; i++) {
22             int ts = in.nextInt();
23             int id = in.nextInt();
24             arr[ts].add(id);
25         }
26         // 遍历每一个时刻
27         for (int i = 1; i <= t; i++) {
28             if (arr[i].size() == 0) // 如果此时刻没有订单,就先不考虑
29                 continue;
30             Collections.sort(arr[i]);
31             int len = arr[i].size();
32             for (int k = 0; k < len; k++) {
33                 int j = k;
34                 while (j < len && arr[i].get(k) == arr[i].get(j))
35                     j++;
36                 int nid = arr[i].get(k);                        // 只有对于有订单的店家才需要更新优先级,其他的用last更新
37                 // 先更新之前没有订单时欠下的
38                 score[nid] = score[nid] - (i - last[nid] - 1);     // 不算开头也不算结尾求长度 结果-1
39                 last[nid] = i;
40                 if (score[nid] < 0) score[nid] = 0;             // 最低优先级是0
41                 if (score[nid] <= 3) level[nid] = false;         // 若优先级小于等于3,从优先缓存中出来
42                 score[nid] = score[nid] + (j - k) * 2;             // 每个订单加2优先级
43                 k = j - 1;                                        // 更新下标
44                 if (score[nid] > 5) level[nid] = true;             // 优先级大于5,加入优先缓存
45             }
46         }
47         int res = 0;
48         for (int i = 1; i <= n; i++) {
49             if (last[i] < t) {
50                 score[i] = score[i] - (t - last[i]);            // 这里就不用减一了,因为此时last[i]不为t的表明最后一刻都没有订单
51                 if (score[i] <= 3)
52                     level[i] = false;
53             }
54             if (level[i])
55                 res++;
56         }
57         System.out.println(res);
58     }
59 }

 

 

posted @ 2022-04-04 10:33  JaineCC  阅读(67)  评论(0)    收藏  举报