第十届蓝桥杯javaB组 G题:外面优先级(java实现)

本文探讨了一种优化算法,用于高效计算外卖店在特定时刻的优先级状态,避免了传统方法中的高时间复杂度问题,确保在大规模数据处理中算法的稳定性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

试题 G: 外卖店优先级
时间限制: 1.0s 内存限制: 512.0MB 本题总分: 20 分
【问题描述】
“饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有
一个优先级,初始时 (0 时刻) 优先级都为 0。
每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减
到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。
如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果
优先级小于等于 3,则会被清除出优先缓存。
给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优
先缓存中。
【输入格式】
第一行包含 3 个整数 N、 M 和 T。
以下 M 行每行包含两个整数 ts 和 id,表示 ts 时刻编号 id 的外卖店收到
一个订单。
【输出格式】
输出一个整数代表答案。
【样例输入】
2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

【样例输出】
1
【样例解释】
6 时刻时, 1 号店优先级降到 3,被移除出优先缓存; 2 号店优先级升到 6,
加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。
【评测用例规模与约定】
对于 80% 的评测用例, 1 ≤ N; M; T ≤ 10000。
对于所有评测用例, 1 ≤ N; M; T ≤ 100000, 1 ≤ ts ≤ T, 1 ≤ id ≤ N

 此解决方案为一般方法会出现算法复杂度过高,导致部分用例超时,也是网上搜索到大部分写法。

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
	static int[] shop=new int[100005];
	static boolean[] isStore=new boolean[100005];
	static ArrayList<Integer>[] timeList;
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		int n=cin.nextInt();
		int m=cin.nextInt();
		int t=cin.nextInt();
		timeList=new ArrayList[t+1];
		for(int i=1;i<=t;i++) {
			timeList[i]=new ArrayList<Integer>();
		}
		for(int i=1;i<=m;i++) {
			int time=cin.nextInt();
			int id=cin.nextInt();
			timeList[time].add(id);
		}
		way1(n);
		int number=0;
		for(boolean is:isStore) {
			if(is) {
				number++;
			}
		}
		System.out.println(number);
	}
	
	//时间复杂度达到10次方必定超时  复杂的原因是内层循环嵌套了一个检查数组中的每个数是否大于0
	public static void way1(int n) {
		
		for(int j=1;j<=timeList.length-1;j++) { //时间复杂度5次方
			ArrayList<Integer> a=timeList[j];
			if(a.size()!=0) {
				for(int shopId:a) {
					shop[shopId]+=3;
					if(shop[shopId]-1>5) {
						isStore[shopId]=true;
					}
				}
			}
			//时间复杂度5次方
			for(int i=1;i<=n;i++) {
				if(shop[i]>0) {
					shop[i]-=1;
					if(shop[i]<=3) {
						isStore[i]=false;
					}
				}
			}
		}
	}
	
}

此解决方法不会出现用例超时现象

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Main {
    static int  N=100005;
    //score 数组记录每个店铺得分
    static int[] score=new int[N];
    //last数组 是每个店铺最后一次接收到订单的时刻
    static int[] last=new int[N];
    //st数组记录是否进入优先缓存区
    static boolean[] st=new boolean[N];
    static ArrayList<Order> list=new ArrayList<Order>();
    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        int n=cin.nextInt();
        int m=cin.nextInt();
        int t=cin.nextInt();
        for(int i=0;i<m;i++) {
            int ts=cin.nextInt();
            int id=cin.nextInt();
            list.add(new Order(ts,id));
        }
        Collections.sort(list);
        for(int i=0;i<m;i++) {
            int j=i;
            Order a =list.get(i);
            int time=a.time; int id=a.id;
            //记录同一时刻,相同id的店铺一共接受j个订单
            while(list.get(j).time==time&&list.get(j).id==id) {
                j++;
                if(j==list.size()) {
                    break;
                }
            }
            //优先级得分要减去 当前店铺在之前最后一次接收订单的时间和当前时刻再次接收到订单的时间差
            score[id]-=time-last[id]-1;
            if(score[id]<0) score[id]=0;
            if(score[id]<=3) st[id]=false;
            last[id]=time;
            //优先级得分要加上 当前时刻 接收到的总订单数(j-i)*2
            score[id]+=(j-i)*2;
            if(score[id]>5) {
                st[id]=true;
            }
            //i下次是从j的位置开始遍历,因为i到j都是同样的id和time,但是要减1,因为执行完了循环体++1
            i=j-1;
        }

        for(int i=1;i<=n;i++) {
            if(last[i]<t) {
                score[i]-=t-last[i];
                if(score[i]<0) score[i]=0;
                if(score[i]<=3) st[i]=false;
            }
        }

        int res=0;
        for(int i=1;i<=n;i++) {
            if(st[i]==true) res++;
        }
        System.out.println(res);
    }
}


class Order implements Comparable<Order>{

    int time;
    int id;

    public Order(int time, int id) {
        super();
        this.time = time;
        this.id = id;
    }
    @Override
    public int compareTo(Order o) {
        // TODO Auto-generated method stub
        if(this.time==o.time) {
            return this.id-o.id;
        }
        return this.time-o.time;
    }
    @Override
    public String toString() {
        return "Order [time=" + time + ", id=" + id + "]";
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值