题解:
按照每个店铺id为第一关键字,时间t为第二关键字升序排序。
把每个店铺看做一个集合label,集合中元素为该店铺的订单时间。(以下叙述均称每一个店铺为集合)
对于每一个集合,按照订单时间先后顺序扫描,扫描过程中记录该店铺的实时状态(是否在缓存中),并记录当前的优先级。
遇到一个新集合时,此时应该判断上一个集合是否满足条件,判断末状态即可,更新答案。
细节:在遇到新集合时,上一个集合的最后一个订单时间可能不是T,那么随着时间流逝,优先级应该随着T减少,此刻应该注意判断。
时间复杂度: $O(M * log M + M)$
C++ 代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int cnt[N];
struct message
{
int t, id;
bool operator < (const message& m)
{
return id < m.id || id == m.id && t < m.t;
}
}m[N];
int main()
{
int n, M, T;
scanf("%d%d%d", &n, &M, &T);
for(int i = 0; i < M; i++) scanf("%d%d", &m[i].t, &m[i].id);
sort(m, m + M);
int cur = 2, ans = 0;
bool flag = false;
for(int i = 1; i <= M; i++)
{
if(m[i].id != m[i-1].id)
{
if(flag && cur - (T - m[i-1].t) > 3) ans++; //注意判断末订单时间
flag = false; //恢复初始值,为当前集合服务
cur = 2;
}
else
{
int diff = m[i].t - m[i-1].t - 1;
if(diff == -1) diff = 0;
cur = max(0, cur - diff);
if(cur <= 3) flag = false;
cur += 2;
if(cur > 5) flag = true;
}
}
printf("%d\n", ans);
return 0;
}