【题解】【CF1041C】Coffee Break

版权声明:本文为博主原创文章,需转载请联系博主。 https://blog.csdn.net/ezoixx130/article/details/82763823

题意:

有n个休息时刻,你需要把这n个休息时刻安排到尽量少的天中,使得每两个休息时刻的间隔大于d分钟,一天有m分钟。

注意两天之间的间隔大于d分钟。

题解:

我们贪心选取时刻,每次把尽量小的时刻安排进这一天中,如果没有能安排进这一天的时刻了,我们就必须新开一天,并且选取最小的时刻安排进第二天中,然后继续贪心。

这样我们必须有一种数据结构来快速查找和删除。

那当然是set啦!

方法就是,开一个set把所有时刻存储起来,然后每次找到最小的能安排进这一天的时刻,把这个时刻安排进这一天。如果找不到就安排一个最小的时刻到第二天。每次安排完一个时刻就把这个时刻从set中删除。找最小的时刻用lower_bound就可以了。

注意:假设我们有一个set,名字为a,我们要查找元素x,使用lower_bound(a.begin(),a.end(),x)的时间复杂度为O(n),而使用a.lower_bound(x)的时间复杂度为O(log(n))

时间复杂度:O(nlog(n))
代码:

#include <bits/stdc++.h>
using namespace std;

#define MAXN 200010

struct data
{
    int val,id;
    bool operator<(const data d)const
    {
        return val<d.val;
    }
}x;
int n,m,d,pos[MAXN];
set<data> a;

int main()
{
    scanf("%d%d%d",&n,&m,&d);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&x.val);x.id=i;
        a.insert(x);
    }
    int now=(*a.begin()).val,cnt=1;
    pos[(*a.begin()).id]=1;
    a.erase(a.begin());
    for(int i=2;i<=n;++i)
    {
        data x;x.val=now+d+1;
        auto p=a.lower_bound(x);
        if(p!=a.end())
        {
            pos[(*p).id]=cnt;
            now=(*p).val;
            a.erase(p);
            continue;
        }
        ++cnt;
        p=a.begin();
        pos[(*p).id]=cnt;
        now=(*p).val;
        a.erase(p);
    }
    printf("%d\n",cnt);
    for(int i=1;i<=n;++i)printf("%d ",pos[i]);
}

猜你喜欢

转载自blog.csdn.net/ezoixx130/article/details/82763823
今日推荐