外卖店优先级qaq(复杂度魔幻)

143 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情

[蓝桥杯 2019 省 A] 外卖店优先级

题目描述

“饱了么”外卖系统中维护着 NN 家外卖店,编号 11NN。每家外卖店都有一个优先级,初始时 (0(0 时刻)优先级都为 00

每经过 11 个时间单位,如果外卖店没有订单,则优先级会减少 11,最低减到 00;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 22

如果某家外卖店某时刻优先级大于 55,则会被系统加入优先缓存中;如果优先级小于等于 33,则会被清除出优先缓存。

给定 TT 时刻以内的 MM 条订单信息,请你计算 TT 时刻时有多少外卖店在优先缓存中。

输入格式

第一行包含 33 个整数 NNMMTT

以下 MM 行每行包含两个整数 tstsidid,表示 tsts 时刻编号 idid 的外卖店收到。

一个订单。

输出格式

输出一个整数代表答案。

样例 #1

样例输入 #1

2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

样例输出 #1

1

提示

样例解释

66 时刻时,11 号店优先级降到 33,被移除出优先缓存;22 号店优先级升到 66

加入优先缓存。所以是有 11 家店 (2(2 号)在优先缓存中。

评测用例规模与约定

对于 80%80\% 的评测用例,1N,M,T100001 \le N,M,T \le 10000

对于所有评测用例,1N,M,T1051 \le N,M,T \le 10^51tsT1 \le ts \le T1idN1 \le id \le N

蓝桥杯 2019 年省赛 A 组 G 题。

分析

挺好的一道模拟题,硬暴力枚举时间,看哪些时间点每次出现订单就加上,否则就减1,这样也可以,但是显然只能得到部分分,具体多少分,emm我去看看,啊这,好像暴力直接AC了,失误失误,但是在强大的acwing下,这题是TLE的(强行解释),虽然但是不得不说数据真水!我们来看看暴力AC代码(恼)!

代码(小插曲)讲道理是O(nT)O(nT)复杂度啊,恼)!

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define PII pair<int,int>
const int N=100100;
PII a[N];
#define x first
#define y second
int n,m,t;
int score[N];
bool st[N];
bool ok[N];
int last[N];
int main(){
	cin>>n>>m>>t;
	for(int i=1;i<=m;i++){
		cin>>a[i].x>>a[i].y;
	}
	memset(st,0,sizeof st);
	memset(score,0,sizeof last);
	sort(a+1,a+m+1);
// 	for(int i=1;i<=m;i++){
// 	    cout<<a[i].x<<" "<<a[i].y<<endl;
// 	}
	for(int i=1;i<=t;i++){
		memset(ok,0,sizeof ok);
		for(int j=1;j<=m;j++){
			if(a[j].x==i){
				score[a[j].y]+=2;
				ok[a[j].y]=1;
			//	cout<<score[a[j].y]<<endl;
				if(score[a[j].y]>5){
					st[a[j].y]=1;
				}
			}
 			else{
 				continue;
 			}
		}
		for(int j=1;j<=n;j++){
			if(ok[j]==0 && score[j]>=1){
				score[j]--;
				if(score[j]<=3) st[j]=0;
			}
		}
	}
	int res=0;
	for(int i=1;i<=n;i++){
		res+=st[i];
		//cout<<score[i]<<" ";
	}
	cout<<res<<endl;
	return 0;
}

okok回归正解,正解其实只要O(m)O(m)的时间复杂度,就是把相同的订单都收集起来,然后每一次分一批处理订单,代码如下:

代码

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#define ll long long
using namespace std;
#define PII pair<int,int>
#define x first
#define y second
const int N=100020;
PII a[N];
int last[N];//i订单上一次出现的时刻
int score[N];//i订单的优先级
bool st[N];//i订单是否处于优先缓存
int res=0;
int main(){
	int n,m,t;
	memset(st,0,sizeof st);
	cin>>n>>m>>t;//n个订单,m条订单消息,t的时间
	for(int i=1;i<=m;i++){
		cin>>a[i].x>>a[i].y;
	}
	sort(a+1,a+m+1);
	for(int i=1;i<=m;){
		int j=i;
		
		while(j<=m && a[j]==a[i]){
			j++;
		}
		int ti=a[i].x,id=a[i].y,cnt=j-i;
		i=j;
		score[id]-=ti-last[id]-1;
		if(score[id]<0) score[id]=0;
		if(score[id]<=3) st[id]=0;
		score[id]+=cnt*2;
		if(score[id]>5) st[id]=1;
		last[id]=ti;
	}
	for(int i=1;i<=n;i++){
		if(last[i]<t){
			score[i]-=t-last[i];
			if(score[i]<=3) st[i]=0;
		}
	}
	for(int i=1;i<=n;i++){
		res+=st[i];
	}
	cout<<res<<endl;
	return 0;
}