Codeforces Round #523 (Div. 2) D. TV Shows

传送门

题意

有n个电视节目,每个节目有开始时间和结束时间。

现在要租电视来看节目,租一台电视花x元,电费每分钟y元。

当节目时间冲突时,要另租电视来看节目

例如节目a播出时间是[2,8],节目b播出时间是[4,7]那么节目a需要用一台电视,节目b需要用另一台电视

现在要看完所有的节目,问租电视+电费的最小花费

题解

按播出时间从早到晚排序,贪心选择大于此节目的结束时间的节目中最早开始播放的节目,设其间隔时间为d

(后面解释贪心算法的正确性,大雾)

如果找到的话

①若dy<x,即等待间隔花的电费小于另租一个电视的花费时,可以用这一个看下一个节目

②若dy>=x,即等待间隔花的电费大于另租一个电视的花费时,那就另租一个电视看下一个节目比较划算

如果没找到的话,也就是在此节目播放期间下一个节目开始播放,那肯定是要另租一个电视来看

现在解释为什么要选择大于此节目的结束时间的节目中最早开始播放的节目

假设有5个节目,开始时间为si,结束时间为ti

其分组可以有这两种

①    1                                      ② 1、3

  2、3           2、4、5

  4、5

第一种是按照优先选择大于此节目的结束时间的节目中最早开始播放的节目,    第二种是尽可能把可以安排在同一台电视上的节目安排好

需要租3台电视,每一台电视的花费为  需要租2台电视,每一台电视的花费为

1、x+(t1-s1)*y 1、x+(t3-s1)*y

2、x+(t3-s2)*y 2、x+(t5-s3)*y

3、x+(t5-s4)*y

总花费1-总花费2=x-(s4-t1)*y

由于在方法一中,节目2和4是在不同电视上的,即(s4-t2)*y>x,所以(s4-t1)*y>x,也就是方法一花费更少

•代码

先按上述思路写了个vector的代码,然后TLE10,然后不知道该怎么改了(还不是因为太菜惹

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f3f
const int mod=1e9+7;
const int maxn=1e5+5;
ll ans;
struct action
{
    ll t1,t2;
}a[maxn];
bool cmp(action x,action y)
{
    return x.t1<y.t1;
}

int main()
{
    int n,x,y;
    cin>>n>>x>>y;
    for(int i=0;i<n;i++)
        cin>>a[i].t1>>a[i].t2;
    sort(a,a+n,cmp);

    vector<action> pos[maxn];
    pos[0].push_back(a[0]);
    int num=1;
    ans=(x+(a[0].t2-a[0].t1)*y)%mod;
    ll flag1;
    int flag2;
    int tail;
    for(int i=1;i<n;i++)
    {
        flag1=inf;
        flag2=-1;
        for(int j=0;j<num;j++)//和每一个电视的最后一个节目比较 以得大于此节目的结束时间的节目中最早开始播放的节目,
        {
            tail=pos[j].size()-1;
            if(a[i].t1>pos[j][tail].t2&&a[i].t1-pos[j][tail].t2<flag1)
            {
                flag1=a[i].t1-pos[j][tail].t2;
                flag2=j;
            }
        }
        if(flag1!=inf)
        {
            if(flag1*y<x)//找到 并且dy<x 加在后面
            {
                tail=pos[flag2].size()-1;
                pos[flag2].push_back(a[i]);
                ans=(ans+((a[i].t2-pos[flag2][tail].t2)*y))%mod;
                continue;
            }
        }
        pos[num++].push_back(a[i]);
        ans=(ans+(x+(a[i].t2-a[i].t1)*y))%mod;
    }
    cout<<ans%mod<<endl;
}
View Code

就借鉴了大佬们的博客(https://www.cnblogs.com/Paul-Guderian/p/10014571.html),发现用的multiset,再去补一下STL惹

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+5;
const int mod=1e9+7;
ll ans;
struct action
{
    ll t1,t2;
}a[maxn];
bool cmp(action x,action y)
{
    return x.t1<y.t1;
}

int main()
{
    int n,x,y;
    cin>>n>>x>>y;
    for(int i=0;i<n;i++)
    {
        cin>>a[i].t1>>a[i].t2;
        ans=(ans%mod+(a[i].t2-a[i].t1)*y%mod)%mod;
    }
    sort(a,a+n,cmp);
    multiset<int> Set;
    multiset<int>::iterator it;
    for(int i=0;i<n;i++)
    {
        it=Set.lower_bound(a[i].t1);
        if(it==Set.begin()||(a[i].t1-*(--it))*y>=x)//新租一个,--it是因为lower_bound是找大于等于这个数的第一个,--就是小于这个数的最大的
        {
            ans=(ans+x)%mod;
            Set.insert(a[i].t2);
        }
        else
        {
            ans=(ans+(a[i].t1-*it)*y)%mod;
            Set.erase(it);
            Set.insert(a[i].t2);
        }
    }
    cout<<ans%mod<<endl;
}
View Code
原文地址:https://www.cnblogs.com/MMMinoz/p/11137119.html