【CF】Day19——Codeforces Round 904 (Div. 2) C
没刷多少好题,仅此一道
C. Medium Design
题目:
思路:
不难,实现要细节
题目大意就是给定我们 n 条线段,然后从中任意选取 k (0 <= k <= n) 条,将线段中的点的值全都加1,最后使得整个 1 ~ m 区间的 max - min 最大
那我们就来分析一下如何选取以及有几种情况呢,我们假设 max 在 x 处,min 在 y 处
那么对于选取一个线段就有以下情况:
①.x和y都在线段内,此时二者都加1,那么对答案是没奉献的
②.x和y都在线段外,此时也是没奉献的
③.x在线段外,y在线段内,此时奉献就会减少1
④.x在线段内,y在线段外,此时奉献会增加1
综上所述,我们肯定是选满足④的线段是最好的,那么怎么选 max 和 min 的位置呢?
显然的,如果我们暴力选那么肯定是会爆掉的,所以我们来观察一下,我们可以发现最小值如果在1处 或者 m处 绝对是最优的,因为如果最小值不在这两点,说明所有线段都能覆盖整个线段
那么实现方法就是很经典的差分求有多少个线段相交于一点
我们让 l 位置的奉献是1,r+1 的奉献是 -1,我们再定义一个sum,从 l 的最小值开始累加,时时记录最大值即可
特别的,我们由于两个端点都有可能是最小值的选取点,所以要两个差分
代码:
#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define int long long
#define yes cout << "YES\n"
#define no cout << "NO\n"
void solve()
{
int n, m;
cin >> n >> m;
map<int, int> a, b;
for (int i = 1; i <= n; i++) {
int l, r;
cin >> l >> r;
if (l != 1) a[l] += 1, a[r + 1] -= 1;
if (r != m) b[l] += 1, b[r + 1] -= 1;
}
int ans = 0, now = 0;
for (auto x : a) {
now += x.second;
ans = max(now, ans);
}
now = 0;
for (auto x : b) {
now += x.second;
ans = max(now, ans);
}
cout << ans << endl;
}
signed main()
{
cin.tie(0)->sync_with_stdio(false);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}