• 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
  • 相关阅读:
    Mysql Explain 详解
    TP5和TP3.2的区别
    Http协议详解
    TCP协议三次握手与四次挥手详解
    一些常规面试问题
    计算机网络常识
    队列与栈的区别
    面向对象
    在浏览器中输入 www.baidu.com 后执行的全部过程
    SVN在ubuntu的安装和使用
  • 原文地址:https://www.cnblogs.com/MMMinoz/p/11137119.html
Copyright © 2020-2023  润新知