数据范围为10^5,故算法时间复杂度最大应为O(nlogn),可以先将每一单按时间非降序排序,然后一次处理每一单,计算店铺i的优先级f[i],这样处理时的时间复杂度为O(m),排序时O(mlogm)。
用f[i]表示店铺i当前的优先级,ne[i]表示i店铺上一单的时间,v[i]标记店铺是否被加入了优先列表。
处理店铺i的一个订单时,首先计算f[i]应该减少多少,若上一个订单的时间ne[i]和当前订单的时间ts的差值大于1,那么f[i]在没有订单的时点内应该减少的优先级数为ts - ne[i] -1;若ne[i] 和ts 的差值小于等于1即两个订单是同一时点或者两个订单是连续的时点,那么f[i]不需要减少,综上,f[i]的减少量可以表示为max(0, i.ts - ne[i.id] - 1),注意f[i]最小为零,所以如果f[i]减到负数时应该将f[i]置为0,f[i]减少完毕后判断店铺i是否应该被移除优先级列表,然后这一单使优先级f[i]增加2,再判断增加后店铺i是否应该加入到优先列表。
处理完所有订单后则任意店铺i在最后一单ne[i]到给定时点t间都没有订单了,f[i]应该减少t - ne[i],此时若优先级小于等于3,则跌出优先列表,最后遍历v[]统计还有多少店铺在优先列表内即可。
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
#define ts first
#define id second
using namespace std;
typedef pair<int,int> pii;
const int N = 1e5 + 5;
int f[N], ne[N];
bool v[N];
int n, m, t, ans;
int main(){
scanf("%d%d%d", &n, &m, &t);
vector<pii >a(m);
for(int i = 0; i < m; i ++)
scanf("%d %d", &a[i].ts , &a[i].id);
sort(a.begin(), a.end());
for(pii i : a){
f[i.id] -= max(0, i.ts - ne[i.id] - 1);
f[i.id] = max(0, f[i.id]);
if(f[i.id] <= 3) v[i.id] = 0;
f[i.id] += 2;
if(f[i.id] > 5) v[i.id] = 1;
ne[i.id] = i.ts;
}
for(int i = 1; i <= n; i ++){
f[i] -= t - ne[i];
if(f[i] <= 3 ) v[i] = 0;
if(v[i]) ans++;
}
printf("%d",ans);
return 0;
}