算法分类:
比较复杂的模拟题
问题描述
https://www.acwing.com/problem/content/1243/
原因分析:
先考虑暴力做法
对于每个给定的订单 包含订单时间和店铺名称 可以枚举所有的订单
1.找到每个订单时间的有订单和没订单的店铺
2.对店铺的优先级进行更新 若没有订单则优先级-1 如有订单则优先级+2 更具优先队列的规则修改st数组的属性
3.枚举所有的店铺 统计处于优先队列中的店铺个数
时间复杂度 O(T*N) 10*10 超时 考虑进行优化
分析可知对于一段时间内的订单 存在很多时刻的店铺没有订单 可以将这些店铺没有订单的时间的优先级处理统一放到有订单的时刻进行处理或者放到最后的T时刻进行处理 这样只需要线性扫描一遍订单 在每个订单时间只需要处理有订单的店铺优先级 简化时间复杂度近似于O(n) 此题细节多 详情看代码
实现代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII;
const int N = 1e5+10;
int last[N];
int scores[N];
bool st[N];
PII orders[N];
int n,m,T;
int main(){
cin>>n>>m>>T;
for(int i=0;i<m;i++) cin>>orders[i].x>>orders[i].y;
sort(orders,orders+m);
for(int i=0;i<m;){
int j = i;
while(j<m && orders[i]==orders[j]) j++;
int t = orders[i].x, id = orders[i].y,cnt = j-i;
i = j;
scores[id] -=t-last[id]-1;//处理当前时刻之前的一段时间没有接到订单的店铺的优先级
scores[id] = max(scores[id],0);
if(scores[id]<=3) st[id] = false;
//以上都是处理当前时刻之前的订单 下面处理当前的订单
scores[id] +=cnt*2;
if(scores[id]>5) st[id] = true;
last[id] = t;
}
//枚举所有的店铺
for(int i=1;i<=n;i++){
//如果当前的店铺的最后一个订单的时间不是T 说明在最后一个时间t t-T之间还需要减去对应的优先级
if(last[i]<T){
scores[i]-=T-last[i];
if(scores[i]<=3) st[i] = false;
}
}
int res =0;
//枚举所有店铺 找到处于优先队列中的店铺 即找到对应店铺st为true的个数
for(int i=1;i<=n;i++) res+=st[i];
cout<<res<<endl;
return 0;
}