2023年码蹄杯二赛 未来战争 题型:差分

107 阅读1分钟

码题集OJ-未来战争 (matiji.net)

思想

image.png

首先我们用差分数组和前缀和把所有的区间都预处理出来,然后我们统计一下每段充能区间和非充能区间的长度,最后求一下最大长度。

注意,当是i是1,i-1是非0时,此时i就是充能区间的开始,同时也是非充能区间的结尾。

当i是0,i-1是非0时,i-1是充能区间的结尾,同时也是非充能区间的开始。

image.png

code

注意

1.需要注意的是我们预处理差分和前缀和数字的时候不要从0处理到n,而是根据题目输入的n个[l,r]区间中统计出最小的l和最大的r,在这个[minl,maxr]之间预处理。

2.注意在统计结果的时候我们的遍历区间范围是[minl,maxr+1]而不是[min,maxr]

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N], d[N];

int minl = 0x3f3f3f3f, maxr = -0x3f3f3f3f;
int ans1, ans2;
int start1, end1, start2 = 0x3f3f3f3f, end2;
int n;
int main()
{
	cin >> n;
	while (n--)
	{
		int l, r; cin >> l >> r;
		minl = min(minl, l);
		maxr = max(maxr, r);
		d[l]++, d[r + 1]--;
	}

	for (int i = minl; i <= maxr; i++)
	{
		a[i] = a[i - 1] + d[i];
	}
	//	for (int i = minl; i <= maxr; i++)
	//	{
	//		cout << a[i];
	//	}

	for (int i = minl; i <= maxr + 1; i++)
	{
		if (a[i] != 0 && a[i - 1] == 0)
		{
			end2 = start1 = i;
			ans2 = max(ans2, end2 - start2);
		}
		if (a[i] == 0 && a[i - 1] != 0)
		{
			end1 = start2 = i - 1;
			ans1 = max(ans1, end1 - start1);
		}
	}
	cout << ans1 << " " << ans2 << endl;

	return 0;
}

image.png