C. Medium Design Codeforces Round 904 (Div. 2)

Problem - C - Codeforces

题目大意:有一个长为m的数组初始全为0,有n个区间[li,ri],每选择一个区间就要令区间内所有数+1,要求选择一些区间,使得数组的最大值-最小值最大,求这个差值

1<=n<=1e5;1<=m<=1e9

思路:我们设取得最大值的位置是i,我们要让这个最大值最大,那么所有包含这个位置的区间都要选,并设这些区间去掉重合部分后组成的大区间为[L,R],那么这个区间内最小值的取值位置一定是L或R,因为假如最小值的取值位置在LR里面,那么可以把这个位置左边或右边的区间删掉同时另一边的最大值仍然等于原来的最大值,最小值又变成了新的大区间的端点。

        所以当整个数组最小值在[L,R]外边时,这时答案就等于最大值,如果在L或R,那么需要把以L为左端点的区间删掉或把以R为右端点的区间删掉,这些区间对最大值和最小值的贡献都是1,所以删掉后ma-mi不变,两种情况取最大值即可。

        考虑如何求区间最大值,因为这题m的范围不能开数组,所以我们用对组数组记录区间的端点,左端点就是{位置,1},右端点就是{位置+1,-1},然后将所有端点从小到大排序,遍历这总共最多2e5个端点,维护前缀和同时维护最大值即可。

//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
const int N = 1e5 + 5;
int n;
pair<int, int>a[N];
void init()
{
	
}
void solve()
{
	cin >> n;
	int m;
	cin >> m;
	init();
	for (int i = 1; i <= n; i++)
	{
		int x, y;
		cin >> x >> y;
		a[i] = { x,y };
	}
	vector<pair<int,int>>num1,num2;
	ll ma = 0;
	for (int i = 1; i <= n; i++)
	{
		if (a[i].first != 1)
		{//左端点不是1的
			num1.push_back({ a[i].first,1 });//左端点是+1
			num1.push_back({ a[i].second + 1,-1 });//右端点是-1
		}
		if (a[i].second != m)
		{//右端点不是m的
			num2.push_back({ a[i].first,1 });
			num2.push_back({ a[i].second + 1,-1 });
		}
	}
	sort(num1.begin(), num1.end());//从小到大排序
	sort(num2.begin(), num2.end());
	int las = 0;//当前的下标
	ll cnt = 0;//差分数组前缀和
	for (int i = 0; i < num1.size(); i++)
	{//遍历所有端点
		ma = max(ma, cnt);
		cnt += num1[i].second;
		las = num1[i].first;
	}
	las = 0, cnt = 0;
	for (int i = 0; i < num2.size(); i++)
	{
		ma = max(ma, cnt);
		cnt += num2[i].second;
		las = num2[i].first;
	}
	cout << ma;
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t;
	cin >> t;
	//t = 1;
	while (t--)
	{
		solve();
	}
	return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timidcatt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值