输入样例:
2 6 6
1 1
5 2
3 1
6 2
2 1
6 2
输出样例:
1
样例解释
66 时刻时,11 号店优先级降到 33,被移除出优先缓存;22 号店优先级升到 66,加入优先缓存。
所以是有 11 家店 (22 号) 在优先缓存中。
解题思路:
最直接的暴力想法是:通过枚举每个店的 0~ t的时间来判断到t时刻时,优先级是否在缓存中。但由于店数和时间都是10^5,平方的复杂度肯定会超时,并且因为要同时记录店铺,时间,订单数,需要用到二维数组,也会内存超限。
优化:可以注意到订单的数量也是10^5,与店数规模相同,可以看出平均每个店只有一个订单,是非常离散化的,所以当遍历订单时,时间复杂度可以降为O(n)。
可以先按订单的时间排序,依次遍历,遍历每份订单时,由于时间并不连续,所以为了可以知道上一份订单的时间(用来降低优先级),需要开一个数组,用来表示每个店最后一次出现订单的时刻,可以直接算出"一长段"时间的优先级,遍历完时,还需要将与t之前的没有出现订单的优先级降低。同时再开一个数组再记录每个店是否在优先缓存中,最后统计数量。
Java代码:O(nlogn)
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] split = br.readLine().split(" ");
int n = Integer.parseInt(split[0]);//外卖店数量
int m = Integer.parseInt(split[1]);//订单总数
int t = Integer.parseInt(split[2]);//时间
int []pri = new int[n + 1];//priority:优先先数组 pri[i] = j: 表示第i个店的优先级为j
int []last = new int[n + 1];//last[i]=j :表示第i个店最近一次有订单的时间是第j秒
boolean []flag = new boolean[t + 1];//表示该店是否已经进入优先缓存中
List<Inf1241> list = new ArrayList<>();//存储订单
for(int i = 0; i < m; i++) {
split = br.readLine().split(" ");
int ts = Integer.parseInt(split[0]);
int id = Integer.parseInt(split[1]);
list.add(new Inf1241(ts, id));
}
Collections.sort(list);//将所有订单按订单的时间排序
for(int i = 0; i < m; ) {//遍历订单,因为可能有重复订单,i的下标由重复订单的数量决定
int j = i;
while(j < m && list.get(j).ts == list.get(i).ts && list.get(j).id == list.get(i).id) j++;//循环结束时,j指向新的一份订单
int ts = list.get(j - 1).ts, id = list.get(j - 1).id, cnt = j - i;//cnt:有重复订单的数量
i = j;//方便下一次循环
pri[id] -= ts - last[id] - 1;//因为订单的时间不是连续的,通过last数组处理之前的优先级(注意边界)
if(pri[id] < 0) pri[id] = 0;//优先级最低为0
if(pri[id] <= 3) flag[id] = false;
pri[id] += cnt * 2;//处理此时的新的订单
if(pri[id] > 5) flag[id] = true;
last[id] = ts;//记录该店最后一次有订单的时间
}
for(int i = 1; i <= n; i++) //最后一段时间可能存在有店持续没有订单,需要降低优先级
if(last[i] < t) {
pri[i] -= t - last[i];//(注意边界)
if(pri[i] <= 3) flag[i] = false;
}
int ans = 0;
for(boolean data : flag) if(data) ans++;
System.out.println(ans);
}
}
class Inf1241 implements Comparable<Inf1241>{
int ts;
int id;
public Inf1241(int ts, int id) {
this.ts = ts;
this.id = id;
}
@Override
public int compareTo(Inf1241 o) {
if(this.ts != o.ts) return this.ts -o.ts;
else return this.id - o.id;
}
}
Java代码:O(n^2)
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] split = br.readLine().split(" ");
int n = Integer.parseInt(split[0]);//店铺数
int m = Integer.parseInt(split[1]);//订单总数
int t = Integer.parseInt(split[2]);//时间
int [][]pri = new int[n + 1][t + 1];//优先缓存
for(int i = 0; i < m; i++) {
split = br.readLine().split(" ");
int ts = Integer.parseInt(split[0]);
int id = Integer.parseInt(split[1]);
pri[id][ts]++;//表示第id个店第ts秒的订单数量
}
int ans = 0;
for(int i = 1; i <= n; i++) {//枚举外卖店
int s = 0;//第i个店的优先级
for(int j = 1; j <= t; j++) {//枚举时间
if(pri[i][j] != 0) {//有订单时
s += pri[i][j] * 2;
}else {//没有订单
if(s > 0)s--;
}
}
if(s > 5)ans++;
else if(s == 4 && pri[i][t] == 0 && t >=1 && pri[i][t - 1] == 0)ans++;//优先级4可能是被降下来的,仍然在缓存中
else if(s == 5 && pri[i][t] == 0)ans++;
}
System.out.println(ans);
}
}