分析:
这是一道模拟题,朴素的求解思路是:将M条订单信息先按时间从小到大排序、时间相同再按外卖店序号从小到大排序,时间复杂度为O(MlogM);然后依次处理每条订单信息,对每条订单信息,可能要更新N家外卖店的优先级,所以时间复杂度为O(MN)。注意,所有订单都是T时刻以内的
上述算法的时间复杂度是O(MN),当1≤N,M,T≤10000时,是可以在1秒之内运算完毕的。但如果N,M,T取到100000,上述算法就不能在1秒之内运算完毕了
在处理每条订单信息时,为什么可能要更新N家外卖店的优先级呢?因为:假设每条订单的时间不同,则该订单的外卖店优先级要增加,其他外卖店的优先级要降低。但如果前后几条订单的时间相同呢?哪些外卖店优先级要调整,很复杂!
定义两个数组:
1)p:长度为N,保存N家外卖店的优先级,每个元素初值为0
2)last:长度为N,保存N家外卖店上一个订单的时刻,每个元素初值为0
更好的求解思路是:1)合并订单——时间相同、外卖店相同的订单统一处理;2)对每条订单,只调整对应外卖店优先级,其他外卖店不用处理,因为st数组保存了每家外卖店上一个订单的时刻,所以这样处理完全是可行的
该算法的时间复杂度为:max(O(MlogM), O(M), O(N) )
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int maxn = 100010;
const int maxm = 100010;
int N, M, T;
int p[maxn]; //记录每家外卖店的优先级(初值为0)
int last[maxn]; //记录每家外卖店上一个订单时刻(初值为0)
bool st[maxn]; //每家外卖店是否在优先缓存中的标志
PII order[maxm]; //存M条订单
int main(){
cin >> N >> M >> T;
for(int i=0;i<M;i++)
cin >> order[i].first >> order[i].second;
//二级排序:先按时刻,再按外卖店序号
sort(order, order+M);
for(int i=0;i<M; ){
int j = i;
while(j<M and order[j]==order[i]) j++; //时间和外卖点编号都相同的订单
int t = order[i].first, id = order[i].second, cnt = j-i; //cnt:订单数
i = j;
p[id] -= t - last[id] - 1; //先减去没有订单的时刻(t时刻是有订单)
if(p[id]<0) p[id] = 0;
if(p[id]<=3) st[id] = false; //退出优先缓存
p[id] += cnt*2;
if(p[id>5]) st[id] = true;
last[id] = t; //维护外卖店的last
}
for(int i=1;i<=N;i++){
if(last[i]<T){
p[i] -= T - last[i];
if(p[i]<=3) st[i] = false;
}
}
int ans = 0;
for(int i=1;i<=N;i++)
ans += st[i];
cout << ans << endl;
return 0;
}