【第一届文翁杯现场竞技赛T2】蜀石经

【题目】

传送门

题目描述:

今年是石室中学 2160 2160 2160 年校庆年。CCTV 国家宝藏节目联合中国国家图书馆赠送给学校一份珍贵的礼物——蜀石经拓本的复制本,让蜀石经重回石室。

同学们听说了这个消息后,纷纷希望一睹真容。学校在校史馆展出了这件国宝,今天有 n n n 个同学去参观,排起了长龙。因为学习紧张时间宝贵,我们决定让每个同学登记自己的时间安排。

你现在拿到了这份时间表,知道了对于第 i i i 个同学,他计划在 a i a_i ai 时间来看到这件国宝,他的欣赏时间为 t i t_i ti,他在欣赏的时间段中其他到达的同学智能排队等待,当一个人欣赏完后,有多个同学在等待,就会让操行分高的学生先欣赏(一个人恰好在一个人欣赏完离开时到达也认为是在等待)。当然,如果一个时间点没有任何人在欣赏,但同时有多个人是同一时间到,也是按操行分最高的先欣赏。

请你计算出所有同学在队伍中等待的时间(即对于 i i i,等待时间为 a i a_i ai 到他开始欣赏的时间)的最大值。

输入格式:

输入的第一行包含 n n n

以下 n n n 行按操行分高到低的顺序给出了 n n n 1 ≤ n ≤ 1 0 5 1\le n\le10^5 1n105)个同学的时间安排 。每行包含一个人的 a i a_i ai t i t_i ti

所有的 t i t_i ti 为不超过 1 0 4 10^4 104 的正整数,所有的 a i a_i ai 为不超过 1 0 9 10^9 109 的正整数。

输出格式:

输出所人中的最长等待时间。

样例数据:

输入
5
25 3
105 30
20 50
10 17
100 10

输出
10

提示:

【样例解释】

一共有 5 5 5 个人,第 4 4 4 个人最先到(时间 10 10 10),第一个欣赏。

4 4 4 欣赏完(时间 27 27 27)后,第 1 1 1 3 3 3 个人都到达了,由于第一个人操行分高,所以 1 1 1 先欣赏(第 1 1 1 个人等待了 2 2 2 个单位时间)。

1 1 1 欣赏完(时间 30 30 30)后,第 3 3 3 个人开始欣赏(一共等待了 10 10 10 个单位时间)。

3 3 3 欣赏完后一直到时间 100 100 100,第 5 5 5 个人到达(没有等待)。

5 5 5 个人欣赏的时候,第 2 2 2 个人到了,在 5 5 5 个单位时间后开始欣赏。

那么综上,等待最多的是第 3 3 3 个人,等待时间最多为 10 10 10


【分析】

一道比较水的题。

这道题的关键应该就是找每个人进去观赏的时间点。

先对所有人按照到达时间排序,第一个到的人肯定是最先观赏的,然后就把第一个人还没观赏完就到了的人丢进优先队列了(以操行分排的大根堆),下一个观赏的人就是在堆顶的那个人。按照这个模拟就可以了。

最后的时候, a n s = m a x { e n t e r i − a i } ans=max\{enter_i-a_i\} ans=max{enteriai} e n t e r i enter_i enteri 记录的是进去观赏的时间点)。


【代码】

#include
#include
#include
#include
#define N 100005
using namespace std;
int enter[N];
struct student{int start,t,id,Score;}a[N];
priority_queue<student>q;
bool operator<(const student &p,const student &q){return p.Score<q.Score;}
bool comp(const student &p,const student &q){return p.start<q.start;}
int main()
{
	int n,i,sum=0;
	scanf("%d",&n);
	int tot=n;
	for(i=1;i<=n;++i)
	{
		scanf("%d%d",&a[i].start,&a[i].t);
		a[i].Score=tot--;
	}
	sort(a+1,a+n+1,comp);
	for(i=1;i<=n;++i)  a[i].id=i;
	q.push(a[1]);
	int last=2,lasttime=0;
	while(sum<n)
	{
		if(!q.empty())
		{
			sum++;
			student now=q.top();q.pop();
			enter[now.id]=max(now.start,lasttime);
			lasttime=enter[now.id]+now.t;
			for(i=last;i<=n;++i)
			{
				if(a[i].start>lasttime)
				{
					last=i;
					break;
				}
				q.push(a[i]);
			}
		}
		else  q.push(a[last++]);
	}
	int ans=0;
	for(i=1;i<=n;++i)
	  ans=max(ans,enter[i]-a[i].start);
	printf("%d",ans);
	return 0;
}

你可能感兴趣的:(#,模拟)