【贪心】【CF1061D】 TV Shows

Description

给定 (n) 个电视节目和两个参数 (x,y)。你想要看全部的电视节目,但是同一个电视机同一个时刻只能播放一个电视节目,所以你只能多租赁电视机。在时间 ([l,r]) 租赁一台电视机的花费是 (x~+~y~(r - l))。一台电视机不可以在节目没有播放完时中断播放。求最小花费。答案对 (1e9+7) 取模

Input

第一行是三个整数 (n, x, y)

下面 (n) 行每行两个整数 (l,r),代表节目时间

Output

一行一个整数代表答案对 (1e9+7) 取模的结果

Hint

(1~leq~n~leq~10^5~,~1~leq~y~<~x~leq~10^9~,~1~leq~l~leq~r~leq~10^9)

Solution

考虑贪心,有如下结论:

一、如果必须租赁新的电视机,在结束租赁的时间一定的情况下,租赁时间越晚越好。

这个结论显然,因为租赁时间越晚,租赁时长的代价越低。

二、如果前面有好几台空闲的电视机可以用,在不考虑租赁新的电视机时,一定选择上次结束时间最靠后的一台。

例如:

qwq

我们一定选择三号机器而不是一号二号,因为这样“浪费”的时间更少,即从上个节目结束到这个节目开始的时间花费更少。考虑如果后面紧跟着还有一个节目(开始时当前节目未结束),则它会选择一号,与这次选择一号下次选择三号相比,答案不会更劣。

以上是感性的理解结论二,下面给出结论二的证明(参考自官方题解):

先将节目顺序按照左端点排序。因为每个节目时长再乘 (y) 是的花费是不变的,因此我们只比较额外的花费。即租赁新电视机的花费和时的花费。下面的花费均值额外花费

考虑我们有两个用过的电视机 (o1,o2),其中 (r_{o1}~<~r_{o2})(r) 为该电视上个节目的结束时间。当前我们要分配 (i) 这个节目。

下面分三种情况:

第一种:

如果后面不存在一个 (j) 使得从两个中继承过来比新租一个更划算的话,显然把 (o2) 分配给 (i) 更优

第二种:

如果后面存在一个 (j),使得 ((l_j ~-~r_{o2})~y~leq~x~~(1)),但是 ((l_j ~-~r_{o1})~y~>~x~~(2)),我们如果将 (o1) 分配给 (i),那么花费是 ((l_j~-~r_{o2})~y~+~(l_i~-~r_{o1})~y~~(3))。考虑将 (o2) 分配给 (i),那么花费是 ((r_l~-~r_{o1})~y~+~x~~(4))。给 ((2)) 式左右同加 ((l_i~-~r_{o2})~y) 即得 ((l_j ~-~r_{o1})~y~+~(l_i~-~r_{o2})~y>~x~+~(l_i~-~r_{o2})~y),即 ((3)~>~(4)),所以讲 (o2) 分配给 (i) 更优

第三种:

如果后面存在一个 (j),使得 ((l_j ~-~r_{o2})~y~leq~x~~(1)),并且 ((l_j ~-~r_{o1})~y~leq~x~~(2)),那么这两种分配方式分别花费是 ((l_j~-~r_{o2})y~+~(l_i~-~r_{o1})y~=~y(l_j~+~l_i~-~r_{o2}~-~r_{o1}))((l_i~-~r_{o2})y~+~(l_j~-~r_{o1})y~=~y(l_j~+~l_i~-~r_{o2}~-~r_{o1}))。所以上两式是相等的,选择 (o2)(i) 不会更劣。证毕。

那么我们就有如上两个贪心策略,每次比较贪心策略那个更优即可。即:新选择一个电视机租赁或者选择上次结束时间最靠后的一个电视机。根据结论一,如果选上次租赁过的而不是新租赁一个更好的话,因为新租赁电视机的时间被推迟了,答案一定不会更劣。于是这个贪心是正确的。

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long

typedef long long int ll;

namespace IPT {
	const int L = 1000000;
	char buf[L], *front=buf, *end=buf;
	char GetChar() {
		if (front == end) {
			end = buf + fread(front = buf, 1, L, stdin);
			if (front == end) return -1;
		}
		return *(front++);
	}
}

template <typename T>
inline void qr(T &x) {
	rg char ch = IPT::GetChar(), lst = ' ';
	while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
	while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
	if (lst == '-') x = -x;
}

template <typename T>
inline void ReadDb(T &x) {
	rg char ch = IPT::GetChar(), lst = ' ';
	while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
	while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
	if (ch == '.') {
		ch = IPT::GetChar();
		double base = 1;
		while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
	}
	if (lst == '-') x = -x;
}

namespace OPT {
	char buf[120];
}

template <typename T>
inline void qw(T x, const char aft, const bool pt) {
	if (x < 0) {x = -x, putchar('-');}
	rg int top=0;
	do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
	while (top) putchar(OPT::buf[top--]);
	if (pt) putchar(aft);
}

const int maxn = 100010;
const int maxm = 200010;
const int MOD = 1000000007;

struct M {
	int l, r;
	inline bool operator<(const M &_others) const {
		return this->r < _others.r;
	}
};
M MU[maxn];

struct Zay {
	int id, pos;
	bool Is_Begin;
	inline bool operator<(const Zay &_others) const {
		if (this->pos != _others.pos) return this->pos < _others.pos;
		else if (this->Is_Begin ^ _others.Is_Begin) return this->Is_Begin;
		else return this->id < _others.id;
	}
};
Zay CU[maxm];

int n, x, y, cnt, scnt, ans;
int stack[maxm];

int main() {
	freopen("1.in", "r", stdin);
	qr(n); qr(x); qr(y);
	for (rg int i = 1; i <= n; ++i) {
		qr(MU[i].l); qr(MU[i].r);
		Zay &_temp = CU[++cnt];
		_temp.id = i; _temp.pos = MU[i].l; _temp.Is_Begin = true;
		Zay &_tp = CU[++cnt];
		_tp.id = i; _tp.pos = MU[i].r;
	}
	std::sort(CU + 1, CU + 1 + cnt);
	for (rg int i = 1; i <= cnt; ++i) {
		if (CU[i].Is_Begin) {
			ll payd = x + 1ll * (MU[CU[i].id].r - MU[CU[i].id].l) * y;
			if (scnt) {
				if ((1ll * (MU[CU[i].id].r - stack[scnt]) * y) < payd) {
					payd = 1ll * (MU[CU[i].id].r - stack[scnt]) * y;
					--scnt;
				}
			}
			ans = (ans + payd) % MOD;
		} else {
			stack[++scnt] = CU[i].pos;
		}
	}
	qw(ans, '
', true);
	return 0;
}
原文地址:https://www.cnblogs.com/yifusuyi/p/10214984.html