蓝桥杯真题 外卖店优先级
考点
模拟、优化
(我看了好几个题解都把店家和时间挨个遍历了一遍,这样会超时)
(我的代码还有一些问题,现在只能拿60分,但是时间是在范围内的,之后有空再慢慢debug吧,这里做个记录)
题目描述
每经过 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 }

浙公网安备 33010602011771号