1.题目介绍
2.一般想法
(可以着重看优化做法)
首先存储i时刻,j号店,有多少订单;
然后依次遍历每一个时刻的每一家店,
判断哪些店有订单,有订单的话,优先级就加上2*订单数;
其次,判断店铺的优先级是否>5,是的话就进入优先缓存;
如果店铺的优先级<=3,就退出优先缓存;
那些没有订单的店,优先级就-1,注意要保证优先级一直>=0;
最后,遍历所有店铺,看有多少店铺在优先缓存中,输出答案;
但是,根据题目限制,这种做法在数据较大时会超时,拿不到所有分数
#include <bits/stdc++.h>
using namespace std;
int dd[10010][10010];//存储i时刻,j号店,有多少订单;
bool st[10010];//存储j号店是否在优先缓存中
int score[10010];//存储j号店的优先级
int main(){
int N,M,T;
cin>>N>>M>>T;
while(M--)
{
int ts,id;
cin>>ts>>id;
dd[ts][id]++;
}
for(int i=1;i<=T;i++)//遍历每一个时刻的每一家店
for(int j=1;j<=N;j++)
{
if(dd[i][j]>0)//如果i时刻j号店有订单
{
score[j]+=2*dd[i][j];//每有一单优先级加 2,直接2*订单数
}
else//如果外卖店没有订单,则优先级会减少 1,最低减到 0
{
if(score[j]-1>=0)score[j]--;
}
if(score[j]>5)st[j]=true;
if(score[j]<=3)st[j]=false;
}
int res=0;
for(int i=1;i<=N;i++)//遍历每一家店,如果在优先缓存中,res+1,否则res+0;
res+=st[i];
cout<<res;
return 0;
}
不过往往考试比赛中更有现实实际价值。
3.优化做法
我们主要处理有订单的信息,对于连续的没有订单的情况不再逐一处理,而是根据有订单的时间节点一并进行处理。
- 输入m个订单信息,排序(时间t为第一优先级,订单id为第二优先级)
- for遍历订单信息(此时订单已经是按照时间顺序排的)
- 假设当前订单为第i个,循环判断后面有没有相同的订单(即t和id相等)。(有的话一定连续)
- 到第j个时订单不相同,此时相同订单的数量为cnt=j−i
- 下一次for循环从j处开始遍历
- 记录此时的t和id, 计算id的优先权,有两部分
7.解释上面那个,因为此时这几个相同的订单都计算过了不需要再计算了,所以下一次循环要从j开始
8. 循环最后上一次拿到订单的时间last[id]更新为t
9. 如果最后一个订单时刻为T,则没问题。如果不是T,那么最后一个拿到订单时刻到T时刻的这部分减法需要手动计算,即减去最后一个订单时刻与T的差值。换而言之,如果上一个拿到订单的时间last[id]小于T,则优先权 减去 T−last[id]。注意这里不减1,因为T时刻也没订单。如果小于等于3,更新优先缓存
Java代码:
下面的样例代码也有对应注释便于理解
score[i]存第i店铺分数的;
last[i]第i个店铺上一次有订单的情况;
st[i]第i个店铺是否在优先缓存中
#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
const int N=100010;
int n,m,T;//n店铺数量;m订单数量;T时间
int score[N],last[N];
bool st[N];
PII order[N];//所有的订单,存 时间 店铺名
int main()
{
scanf("%d%d%d",&n,&m,&T);
for(int i=0;i<m;i++)scanf("%d%d",&order[i].x,&order[i].y);
sort(order,order+m);//pair自带的排序,双关键词比较
//按照时间顺序排序;时间相同
for(int i=0;i<m;)//有订单才有信息
{
int j=i;
while(j<m&&order[j]==order[i])j++;//处理相同一批(即同一时刻相同店铺有订单),相同则统计
int t=order[i].x,id=order[i].y;//t,id记录的是这一时刻这一店铺有订单的情况
int cnt=j-i;//找了一个j=i+1;两个j=i+2;直接相减即可
i=j;//在j的基础上往后继续寻找
//这里处理的是中间没订单的情况
score[id]-=t-last[id]-1;//与该店铺上一次有订单的时刻相比,比如2时刻到5时刻之间,3 4时刻没有那么减去2即可
if(score[id]<0)score[id]=0;
if(score[id]<=3)st[id]=false;//这里处理的是t时刻之前的信息
//这里处理的是t时刻有订单的情况
score[id]+=cnt*2;
if(score[id]>5)st[id]=true;//处理t时刻的信息
last[id]=t;//表示这一次id店铺有订单的情况,对于之后也就是上一次id店铺有订单的情况
}
for(int i=1;i<=n;i++)
if(last[i]<T)//之后i店铺确实没订单了
{
score[i]-=T-last[i];//这本身也包括T时刻
if(score[i]<=3)st[i]=false;
}
int res=0;
for(int i=1;i<=n;i++)res+=st[i];
printf("%d\n",res);
return 0;
}