AcWing 1241.外卖店优先级

文章讲述了在处理外卖店优先级问题时,原始的朴素方法时间复杂度较高。作者提出改进算法,通过订单优化和店铺衰减优化,将时间复杂度降低到O(T),显著提高了效率。

题目描述

原题链接:1241.外卖店优先级

解题思路

1.朴素做法

首先用一个结构体存储每一个订单的店铺号和时刻。
然后根据订单的时刻和店铺号按从小到大排序。
ac1241_0
可以看出,上述做法的时间复杂度为 o ( T ∗ ( n + m ) ) ≈ o ( T 2 ) = 1 0 10 > 1 0 8 o(T*(n+m)) \approx o(T^2)=10^{10}\gt10^8 o(T(n+m))o(T2)=1010>108
虽然如此,暴力做法依然可以拿到 90 % 90\% 90%的分数。

2.改进做法

可以看出,上述做法的一个缺点是每次枚举 T T T的时候都需要枚举每一个订单和店铺。因此可以考虑在循环内部优化。

(1)订单优化

可以当只有当此时订单的时刻=此时刻时,才进行下一步。

(2)店铺衰减的优化

假如我们不每个时刻都衰减没有订单店铺,而是等到该店铺出现订单时,我们再比较他上一次拿到订单的时刻和本时刻的差距,一次性衰减两个时刻内所有没有订单的时刻。我们可以用last[k]表示第k个店铺上一次接到订单的时刻。
而这种问题我们又需要分两种情况讨论:
情况1: 该段时间出现在T时刻之前
ac1241_1
这个时候我们需要判断j-last[k]是否大于1,如果大于1,那么说明两个时刻之间出现了空,需要进行衰减。

cnt[k] = max(0, cnt[k] - (j - last[k] - 1)); # 与0做比较,防止优先级小于0

情况2: 该段时间截止至在T时刻
ac1241_2
那么就需要判断最后接到订单的时间last[k]T的关系,如果小于T,则说明在某一时刻到T时刻之间有没有接到订单的时段,需要进行衰减。

cnt[k] = max(0, cnt[k] - (t - last[k]));
3.改进做法的时间复杂度

由于我们只枚举每个时刻的订单,因此算法的时间复杂度为 o ( m a x ( T , m ) ) ≈ o ( T ) = 1 0 5 o(max(T,m)) \approx o(T)=10^5 o(max(T,m))o(T)=105

C++代码

朴素算法( o ( T 2 ) o(T^2) o(T2)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100100;
struct Node{
    int ts,id;
}a[N];
bool cmp(Node a, Node b)
{
    return a.ts < b.ts;
}
int n,m,t,cnt[N];
bool ans[N];
int main()
{
    cin >> n >> m >> t;
    for(int i = 1; i <= m; i++)
    {
        int ts,id;
        cin >> ts >> id;
        a[i] = {ts, id};
    }
    sort(a+1, a+1+m, cmp);
    int i = 1;
    for(int j = 1; j <= t; j++)
    {
        int flag[N] = {0};
        for(; i <= m && a[i].ts == j; i++)
        {
            cnt[a[i].id] += 2;
            flag[a[i].id] = 1;
        }
        for(int k = 1; k <= n; k++)
        {
            if(!flag[k] && cnt[k] > 0) cnt[k]--;
            if(cnt[k] <= 3 && ans[k]) ans[k] = false;
            if(cnt[k] > 5 && !ans[k]) ans[k] = true;
        }
        memset(flag, 0, sizeof flag);
    }
    int res = 0;
    for(int k = 1; k <= n; k++)
        if(ans[k]) res++;      
    cout << res;
改进做法( o ( T ) o(T) o(T)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100100;
struct Node{
    int ts,id;
}a[N];
bool cmp(Node a, Node b)
{
    if(a.ts != b.ts) return a.ts < b.ts;
    return a.id < b.id;
}
int n,m,t,cnt[N],last[N];
bool ans[N];
int main()
{
    cin >> n >> m >> t;
    memset(last, 0, sizeof last);
    for(int i = 1; i <= m; i++)
    {
        int ts,id;
        cin >> ts >> id;
        a[i] = {ts, id};
    }
    sort(a+1, a+1+m, cmp);
    int i = 1;
    for(int j = 1; j <= t; j++)
    {
        for(; i <= m && a[i].ts == j; i++)
        {
            int k = a[i].id;
            if(j - last[k] > 1) cnt[k] = max(0, cnt[k] - (j - last[k] - 1));
            if(cnt[k] <= 3) ans[k] = false;
            last[k] = j;
            cnt[k] += 2;
            if(cnt[k] > 5) ans[k] = true;
        }
    }
    for(int k = 1; k <= n; k++)
    {
        if(t - last[k] > 0) cnt[k] = max(0, cnt[k] - (t - last[k]));
        if(cnt[k] <= 3 && ans[k]) ans[k] = false;
    }
    int res = 0;
    for(int k = 1; k <= n; k++)
        if(ans[k]) res++;
    cout << res;
### 外卖订单处理优先级设定方法 在“饱了么”外卖系统中,每家外卖优先级动态变化取决于是否有新订单以及时间流逝的影响。初始状态下,在0时刻所有外卖优先级均为0[^1]。 当外卖在一个时间单位内未收到任何订单时,其优先级会自动降低1分,不过这一数值不会低于零。相反,若有新的订单到来,则该铺的优先级不仅不会下降反而会上升2分。这种机制旨在鼓励持续接单并维持活跃度较高的商家处于更优的服务位置。 对于那些表现特别积极或者受欢迎程度更高的外卖来说,一旦它们的优先级超过5分就会被纳入系统的优先缓存列表里以便获得更好的资源分配和服务支持;然而,如果某个铺的表现不佳导致其优先级降至3分及以下,则会被移除出此特殊待遇名单之外。 为了实现上述功能,可以设计一个简单的模拟程序来跟踪各个时间段内外卖的状态及其对应的优先级别调整情况: ```python class Restaurant: def __init__(self, id): self.id = id self.priority = 0 def update_priority(self, has_order): if not has_order and self.priority > 0: self.priority -= 1 elif has_order: self.priority += 2 # Check cache conditions if self.priority > 5: add_to_cache() elif self.priority <= 3: remove_from_cache() def simulate(T, orders_info): restaurants = {i: Restaurant(i) for i in range(1, N+1)} for t in range(1, T+1): current_orders = get_current_orders(t, orders_info) for r_id, restaurant in restaurants.items(): has_order = r_id in current_orders restaurant.update_priority(has_order) def count_cached_restaurants(restaurants): return sum([r.priority > 5 for _, r in restaurants]) ``` 通过这种方式能够有效地管理和优化不同外卖之间的服务质量和响应速度,从而提升用户体验和平台整体效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值