Gym - 101911A "Coffee Break"

Posted violet-acmer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym - 101911A "Coffee Break"相关的知识,希望对你有一定的参考价值。

传送门

 

题意:

  Monocarp得到一份工作,每天要工作 m 分钟,他有一个爱好,喜欢在休息的时候喝咖啡,但是他的老板不乐意了,就给他规定了个

  时间 d,在 d 分钟内只能喝一杯咖啡。

  现给出Monocarp喝 n 杯咖啡的时间点,问最少需要几天喝完?

  并输出每个时间点的咖啡在第几天喝。

  样例1解释:

  4 5 3

  3 5 1 2

  Monocarp有 n 杯咖啡需要喝,但老板规定,在 3 分钟内只能喝一杯,

  那么在第一天Monocarp可以喝时间点为 1,5 的咖啡;

  第二天可以喝时间点为 2 的咖啡;

  第三天可以喝时间点为 3 的咖啡;

  那么,最少需要三天才能喝完这 n 杯咖啡 ;

  第一杯咖啡 3 在第三天喝,输出 3;

  第二杯咖啡 5 在第一天喝,输出 1;

  第三杯咖啡 1 在第一天喝,输出 1;

  第四杯咖啡 2 在第二天喝,输出 2;

题解:

  根据贪心的思想,对于每一天,尽可能的多喝,这样才会使中天数最少;

  首先将咖啡按时间点从小到大排个序,然后找出第一天最多喝的咖啡,第二天最多和的咖啡,以此类推,

  直到所有咖啡全部喝完。

  那么该怎么找第一天最多和的咖啡呢?

  这里我使用了一个 map 中的 lower_bound() 函数,首先将喝咖啡的 n 个时间点存在 map 的first中。根据 map 的特性,

  他会自动按照 first值 由小到大排序。

  由贪心思想可得,时间点最小(假设为 x)的咖啡要在第一天喝,然后,在 map 中二分查找时间点 ≥ x+d+1 的最小的时刻(假设为 y),

  那么 y 时刻的咖啡也要在第一天喝,接着查找时间点 ≥ y+d+1 的最小时刻,以此类推,直到搜索完所有满足条件的时间点,那么第一天的

  喝咖啡的时间点就搜索完毕了,并且,在确定某一时间点在第一天喝后,要将其从 map 数组中删去,防止后面的重复计数。

  第二天、第三天的搜索情况同理。

AC代码:

技术图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<map>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn=2e5+50;
 8 
 9 int n,m,d;
10 int a[maxn];
11 map<int ,int >ans;//if ans[x]=y : 时间点为x的咖啡在第y天喝
12 map<int ,int >b;//first存储咖啡时间点,second随意
13 
14 void Solve()
15 {
16     for(int i=1;i <= n;++i)
17         b[a[i]]=i;
18 
19     int day=0;
20     int tot=0;
21     map<int ,int >::iterator it;
22 
23     for(it=b.begin();it != b.end();++it)
24     {
25         //当前有tot个时间点已求出解
26         if(tot >= n)
27             break;
28 
29         int x=it->first;
30         if(!ans.count(x))//如果在之前的day中没有筛去x时间点,那么x时间点在第day+1天喝
31         {
32             ans[x]=++day;
33             tot++;
34         }
35         //查找出第day天可以喝的咖啡时间点
36         map<int ,int >::iterator t=b.lower_bound(x+d+1);
37         while(t->first >= x+d+1)
38         {
39             ans[t->first]=ans[x];
40             x=t->first;
41             b.erase(t);
42 
43             t=b.lower_bound(x+d+1);
44             tot++;
45         }
46     }
47     
48     printf("%d
",day);
49     for(int i=1;i <= n;++i)
50         printf("%d ",ans[a[i]]);
51 }
52 int main()
53 {
54     scanf("%d%d%d",&n,&m,&d);
55     for(int i=1;i <= n;++i)
56         scanf("%d",a+i);
57     Solve();
58 
59     return 0;
60 }
View Code

 

以上是关于Gym - 101911A "Coffee Break"的主要内容,如果未能解决你的问题,请参考以下文章

2016"百度之星" - 初赛(Astar Round2A) 1006 Gym Class 拓扑排序

gym101666题解

2016"百度之星" - 初赛(Astar Round2A)1006 Gym Class(HDU5695)——贪心+拓扑排序

(寒假开黑gym)2018 USP Try-outs

(寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest

(寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)