其他分享
首页 > 其他分享> > Codeforce 1061 :D. TV Shows(multiset + 贪心 + 构造)

Codeforce 1061 :D. TV Shows(multiset + 贪心 + 构造)

作者:互联网

题目大意:有 n 个电视节目,每个节目有一个播放时间[ai,bi],你可以租用电视机来播放节目,租用一台电视机要先付 xxx(类似定金什么的),如果你在[a,b]时间段租用,你需要付租用的费用:y(ba)y * (b - a)y∗(b−a)。当电视机播放一个节目时,电视机不能中途跳转到播放其它节目,一个节目被电视机播放时,也不能播到一半然后转到其它电视机去播放。问如何使租用电视机使得你可以播放所有的节目,且花费的费用最少。
在这里插入图片描述

题解:跟着样例分析一下,如果租用一台电视连续播放好几个节目,例如两个,那么你将多付两个节目之间的间隔时间的钱(后一个节目的开始时间扣去前一个节目的结束时间),如果你另外租一台电视机来播放另外一个节目,你不用多付节目之间间隔时间的租用费,但你需要付另外一台电视机的定金,思考一下会发现:当两个节目之间的间隔小于等于xy\lfloor \frac{x}{y}\rfloor⌊yx​⌋,租一台电视机连着播放是比较赚的,否则另外租一台比较赚,如果两个节目时间段相交,那么只能另外再租一台了。

可以贪心构造租用方案,将节目按左端点排序(这个排序只是为了让决策有序),判断当前节目可以被那个已经租用的电视机播放:设当前节目的左端点为 l[i]l[i]l[i],租用的第 k台电视目前播放的最后一个节目的右区间是R[k]R[k]R[k],查找是否存在已租用的电视播放的最后一个节目的右区间在[l[i]d,l[i]1][l[i] - d,l[i] - 1][l[i]−d,l[i]−1]范围内,找尽量靠右的,间隔时间越短你多付的钱越少,如果不存在这样的电视那么你另外租一台来播放这个节目一定更赚。

维护可以用multiset,注意已租用的电视机播放的节目有增加时需要删除掉原来这个电视,然后将新的插入到set中,整体复杂度为 nlognn*lognn∗logn(也可以考虑用权值线段树,但需要在叶子结点维护一个桶记录所有的电视机,空间开销比较大,还需要离散化之类的操作)

代码

#include<bits/stdc++.h>
using namespace std;
#define lson rt << 1,l,mid
#define rson rt << 1 | 1,mid + 1,r
const int maxn = 2e6 + 10;
const int mod = 1e9 + 7;
typedef long long ll;
int L[maxn],R[maxn],cnt;
int n,x,y;
int t[maxn],tot,p;
struct ss{
	int l,r;
	bool operator < (const ss & rhs) const {
		if(l == rhs.l) return r < rhs.r;
		return l < rhs.l;
	}
}a[maxn];
int mul(int a,int b) {
	return (int)((1ll * a * b) % mod);
}
struct tt{
	int l,r,id;
	tt(int li = 0,int ri = 0,int idi = 0) {
		l = li;r = ri;id = idi;
	}
	bool operator < (const tt & rhs) const {
		if(r == rhs.r) return l < rhs.l;
		return r < rhs.r;
	}
};
multiset<tt> st;
int main() {
	scanf("%d%d%d",&n,&x,&y);
	tot = cnt = 0;
	int d = x / y;
	for(int i = 1; i <= n; i++) {
		scanf("%d%d",&a[i].l,&a[i].r);
	}
	sort(a + 1,a + n + 1);
	for(int i = 1; i <= n; i++) {
		auto t = st.lower_bound(tt(0,a[i].l,0));
		auto u = t;
		if(u != st.begin()) u--;
		if(t == st.begin() || u -> r < a[i].l - d) {
			++cnt;
			L[cnt] = a[i].l;
			R[cnt] = a[i].r;
			st.insert(tt(L[cnt],R[cnt],cnt));
		}
		else {
			int z = u -> id;
			st.erase(u);
			R[z] = a[i].r;
			st.insert(tt(L[z],R[z],z));
		}
	}
	ll ans = mul(cnt,x);
	for(int i = 1; i <= cnt; i++) {
		ans += mul(R[i] - L[i],y);
		ans %= mod;
	}
	printf("%lld\n",ans);
	return 0;
}

标签:cnt,1061,节目,一台,TV,电视机,Codeforce,租用,播放
来源: https://blog.csdn.net/qq_41997978/article/details/99698032