[补题记录] Codeforces Round 904 (Div. 2)(C)

URL:https://codeforces.com/contest/1884

目录

C

Problem/题意

Thought/思路

Code/代码


C

Problem/题意

有一个长度为 M 的序列,初始值都为 0。

现在给出 N 个区间 [l, r],当选择某个区间时,可以让该区间内的数都 + 1。

对于每一种选择方案,其代价为:最大的数 - 最小的数。

问如何选择区间,使得代价最大。

Thought/思路

最核心的一点就是:不相交的两个区间,无法为答案带来任何贡献。

所以我们维护的方案,其内的区间,一定都是相交的:

  • 那么对于最终答案而言,一定会选中 N 个区间中的某一个,所以只需要对每一个区间都判断当前有多少个区间与其相交即可,这样能求出最大值。
  • 最小值的维护只需要通过判断相交的区间中,有多少个包含了 1 或者 m,取 1 或者 m 位置的最小值即可。

既然要求方案内区间是相交的,所以我们可以使用优先队列,队列大小就是最大值,出队入队过程中又可以维护 1 或者 m 的大小。

Code/代码

#include "bits/stdc++.h"

#define int long long
#define pii std::pair
#define x first
#define y second

int n, m;

void solve() {
	std::cin >> n >> m;
	std::vector  v(n + 1);

	for (int i = 1; i <= n; ++ i) {
		std::cin >> v[i].x >> v[i].y;
	}
	std::sort(v.begin() + 1, v.end(), std::less());

	std::priority_queue , std::greater> pq;
	int ans = 0, l = 0, r = 0;
	
	for (int i = 1; i <= n; ++ i) {
		while (!pq.empty()) {
			auto tmp = pq.top(); 

			if (tmp.x < v[i].x) {
				pq.pop();
				if (v[tmp.y].x == 1) l --;
				if (v[tmp.y].y == m) r --;
			} else {
				break;
			}
		}

		pq.push({v[i].y, i});
		if (v[i].x == 1) l ++;
		if (v[i].y == m) r ++;

		ans = std::max(ans, pq.size() - std::min(l, r));
	}
	std::cout << ans << "\n";
}

signed main() {
	int t; std::cin >> t;
	while (t --) {
		solve();
	}
}

你可能感兴趣的:(补题记录,c语言,开发语言,算法,动态规划)