Codeforces Round #523 (Div. 2) D. TV Shows(multiset+思维)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luyehao1/article/details/84937546

题目链接:

D. TV Shows

题意:

有 n 个电视节目,播放的时间区间为 [li,ri] 。同一时间,不同的节目不能在同一台电视上播放。一个节目必须完整的在一台电视上播放完。现在租一台电视需要先付 x 块钱,之后每分钟要付 y 块钱,即租一台电视从时间区间 [a,b] 需要付 x + (b-a)*y 块钱。问看完所有的节目至少需要多少钱。

思路:

把所有节目按开始时间升序排序,若开始时间相同,按结束时间升序排序。排序后依次遍历所有节目,对于节目 i,去找之前的节目中结束时间小于节目 i 的开始时间的,且离的最近的,若两者的时间差*y<=x,那么两者可以合并(即在同一电视上播放),否则,需要新租一个电视。

如何找之前的节目中结束时间小于节目 i 的开始时间的,且离的最近的?首先想到二分查找,但结束时间并不是有序的,因此想到set(会自动排序)。但本题set不行,因为set会自动去重,这会导致错误答案。因此使用multiset,它与set的唯一区别就是不会自动去重。

关于思路的一些证明:

1. 所有节目必须先按开始时间升序排序,不能先按结束时间升序排序:

例子:

————    ——————

                           ——

2. 如下那种选择更优?(假设都是可以合并的)

            ——           ——                     |                    ——         ————————

——————    ——————        |        ——————        ——

其实这两种情况是一样的,即间隔之和相同,可自己画图试试。

3. 如下那种选择更优?

    ————               ———— (不能合并)      |            ————         ———————(可以合并)

——————     —————— (可以合并)    |        ——————         ———— (可以合并)

这其实和2同理,因为两者的间隔之和相同,所以后者相当于前者两个都合并了,所以后者多付的费用肯定大于前者。

Code:

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

typedef long long ll;

const int MAX = 1e5+10;
const ll mod = 1e9+7;

struct Point{
    ll l,r;
    //定义 < ,用于lower_bound的排序
    bool operator < (const Point &a) const {
        if(r==a.r){
            return l<a.l;
        }
        return r<a.r;
    }
};

int n;
ll x,y;
Point op[MAX];
multiset<Point>s;

bool cmp(Point p,Point q){
    if(p.l==q.l){
        return p.r<q.r;
    }
    return p.l<q.l;
}

int main()
{
    scanf("%d%lld%lld",&n,&x,&y);
    for(int i=0;i<n;i++){
        scanf("%lld%lld",&op[i].l,&op[i].r);
    }
    sort(op,op+n,cmp);
    multiset<Point>::iterator pos;
    for(int i=0;i<n;i++){
       //w.l需要<=0,这样pos--才是我们想要的结果
       Point w = Point{0,op[i].l};
       pos = s.lower_bound(w);
       if(pos==s.begin()){
          s.insert(op[i]);
       }
       else{
          pos--;
          Point tmp = *pos;
          if((op[i].l-tmp.r)*y>x){
             s.insert(op[i]);
          }
          else{
             tmp.r = op[i].r;
             s.erase(pos);
             s.insert(tmp);
          }
       }
    }
    ll ans=0;
    for(pos=s.begin();pos!=s.end();pos++){
       Point now = *pos;
       ans = (ans+x+(now.r-now.l)*y%mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/luyehao1/article/details/84937546