Codeforces1061 D. TV Shows(贪心+multiset二分)

题意:

有n个电视节目,第i个电视节目的观看区间是[li,ri]
你可以同时看多台电视,但是观看区间有交集的两个电视节目不能在同一台电视上观看,
租用一台新电视需要x元,每增加一分钟需要y元
在时段[a,b]租用一台电视的费用是x+y∗(b−a)请问要看完所有电视节目至少需要多少钱。

数据范围:n<=1e5,l,r<=1e9

解法:

这题主要在于如何处理:两个不相交节目,可能用同一台电视,尽管中间会有空闲时间
因为租用一台新电视需要x元,而可能存在两个节目中间的空闲时间*y<x,这时候用同一台更优

将节目按左端点从小到大排序,遍历,在multiset找<=l的最大值(multiset存节目的右端点),
判断这两个节目连接起来的花费小还是新买一个电视的花费小即可。

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=1e5+5;
const int mod=1e9+7;
struct Node{
    int l,r;
}a[maxm];
int n,m;
bool cmp(Node a,Node b){
    if(a.l!=b.l)return a.l<b.l;
    return a.r<b.r;
}
signed main(){
    int n,x,y;cin>>n>>x>>y;
    for(int i=1;i<=n;i++){
        cin>>a[i].l>>a[i].r;
    }
    sort(a+1,a+1+n,cmp);
    multiset<int>s;
    int ans=0;
    for(int i=1;i<=n;i++){
        if(s.empty()){//只能买新的
            s.insert(a[i].r);
            ans+=x+(a[i].r-a[i].l)*y;
        }else{
            auto it=s.lower_bound(a[i].l);
            if(it==s.begin()){//没有小于他的
                s.insert(a[i].r);
                ans+=x+(a[i].r-a[i].l)*y;
            }else{//有小于他的
                it--;//找到小于他的最大值
                int link=(a[i].r-*it)*y;//连接需要的费用
                int buy=x+(a[i].r-a[i].l)*y;//新买一个电视需要的费用
                if(link<buy){
                    ans+=link;
                    s.erase(it);
                    s.insert(a[i].r);
                }else{
                    ans+=buy;
                    s.insert(a[i].r);
                }
            }
        }
        ans%=mod;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107552245
今日推荐