2019年第十届蓝桥杯省赛 C++大学A组 G题 外卖店优先级【模拟】

传送门:AcWing 1241. 外卖店优先级 / 蓝桥杯2019年第十届真题

思路

将相同时刻的订单汇总到一起,然后遍历每个时刻。

只考虑有订单的时刻,对于时刻 i i i,先汇总相同店的订单数,然后遍历所有订单,每个订单包含店的编号信息(假设店编号为 i d id id),维护店 i d id id上次出现订单的时刻(假设为 l a s t [ i d ] last[id] last[id]),那么店 i d id id之前有 i − l a s t [ i d ] − 1 i-last[id]-1 ilast[id]1 的时间都没有订单,此时优先级需要先减去这段没有订单的时间,若优先级<=3,则将店 i d id id移出缓存队列;然后优先级加上 n u m num num个订单带来的优先级 2 ∗ n u m 2*num 2num,若优先级>5,则进入缓存队列。

最后还需要遍历所有 T T T时刻无订单的店,它们最后一次出现订单的时刻到 T T T时刻这段时间就是其优先级的减小值,同时更新是否被移出缓存队列。

T T T个时刻, m m m个订单, n n n个店,时间复杂度大约是 O ( T + m + n ) O(T+m+n) O(T+m+n),因为对于小于 T T T的时刻并没有更新所有店的优先级,而只是更新了有订单的店的优先级,只需要在最后的 T T T时刻更新一次所有店的优先级即可。

AC代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,T,last[N],sum[N];
bool f[N]; // 是否在缓存队列中
vector<int>ans[N];
unordered_map<int,int>vis;
int main()
{
    
    
    ios::sync_with_stdio(false);
    cin>>n>>m>>T;
    int t,id;
    for(int i=1;i<=m;i++)
    {
    
    
        cin>>t>>id;
        ans[t].push_back(id); // t时刻编号为id的店有订单
    }
    memset(last,-1,sizeof(last));
    for(int i=1;i<=T;i++) // 遍历时间
    {
    
    
        if(ans[i].size()) // i时刻有订单
        {
    
    
            int sz=ans[i].size();
            vis.clear();
            for(int j=0;j<sz;j++)
            {
    
    
                int id=ans[i][j];
                vis[id]++; // 汇总相同店的订单数
            }
            for(auto it:vis)
            {
    
    
                int id=it.first; // 店id
                int num=it.second; // 订单数num
                if(last[id]==-1) // 店id第1次出现
                {
    
    
                    sum[id]=num*2;
                    last[id]=i;
                    if(sum[id]>5)f[id]=1; // 放入缓存队列
                }
                else
                {
    
    
                    int d=i-last[id]-1;
                    sum[id]=max(0,sum[id]-d);
                    if(sum[id]<=3)f[id]=0; // 移出缓存队列
                    sum[id]+=num*2;
                    if(sum[id]>5)f[id]=1; // 放入缓存队列
                    last[id]=i;
                }
            }
        }
        if(i==T) // 处理T时刻无订单的店
        {
    
    
            for(int j=1;j<=n;j++) 
            {
    
    
                if(last[j]!=T) // 店j的最后一次订单出现在T时刻之前
                {
    
    
                    int d=T-last[j]; 
                    sum[j]=max(0,sum[j]-d);
                   if(sum[j]<=3)f[j]=0; // 移出缓存队列
                }
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++)
        if(f[i])cnt++;
    printf("%d\n",cnt);
    return 0;
}
/*
2 6 6
1 1
5 2
3 1
6 2
2 1
6 2
ans:1
2 6 8
1 1
5 2
3 1
6 2
2 1
6 2
ans:1
2 6 9
1 1
5 2
3 1
6 2
2 1
6 2
ans:0
1 3 5
1 1
2 1
3 1
ans:1
1 3 6
1 1
2 1
3 1
ans:0
*/

猜你喜欢

转载自blog.csdn.net/ljw_study_in_CSDN/article/details/109069626
今日推荐