洛谷P2082 —P2082 区间覆盖(加强版)题解

这个题想(qia)了我一上午

才发现

思路明白了就简单了!

兴高采烈.jpg

题目传送门

先来说说思路

贪心

从第一个区间开始融合,即 将搭界、相邻或包含的区间融为一体,我将这样处理过的区间称为大区间

使用计数变量将所有大区间长度相加得出结果

以下是程序详细步骤


输入

使用结构体存储所有未经处理的左端点(以下简称(l))及未经处理的右端点(以下简称(r)


预处理

维护两个变量,存储当前左端点(以下简称(L))及当前右端点(以下简称(R)

(这两个变量是用来存储大区间两端端点的)

(l)从小到大排序,如果相同,则将(r)从小到大排


重头戏来了

融合

使用(L)(R)存储第一个(l)(r),也就是母体初始区间的两个端点

使用循环不断往后找与其搭界相邻包含的区间端点,不断更新(R)

最后在没有满足条件的区间时,求出长度,加入计数器中

最后的(L)(R)就是当前大区间的长度

最后贴上代码

码风丑陋,敬请见谅
#include<iostream>
#include<algorithm>
using namespace std;
struct hhh{
	long long l;
	long long r;//不开long long见祖宗
};
bool cmp(hhh a,hhh b)//比较函数
{
	if(a.l==b.l)//如果l相等
		return a.r<b.r;//按照右端点排序
	return a.l<b.l;//优先按照左端点排序
}
int main()
{
	long long i,n,cnt=0,L,R;//L和R用于存储大区间两端端点
	hhh a[100005];
	cin>>n;
	for(i=0;i<n;i++)
		cin>>a[i].l>>a[i].r;//输入
	sort(a,a+n,cmp);//排序,做预处理
	for(i=0;i<n;)//这里没加i++是因为在循环里,变量"i"有变动
	{
		L=a[i].l;
		R=a[i].r;//第一个未经处理的左右端点
		i++;//判断下一个端点
		for(;i<n&&a[i].l<=R+1;i++)//按顺序判断下一个端点,R+1是判断相邻 
			R=max(R,a[i].r);//在这里卡过一次,一定要加max函数,这是包含的情况
		cnt+=R-L+1;//将长度放入计数器
        //一次循环过后,循环变量"i"已经是下一个未经处理的区间了,不必再加一 
	}
	cout<<cnt;//输出结果 
	return 0;
}

留个赞再走吧

完结撒花 (。・∀・)ノ

我要拿金牌!
原文地址:https://www.cnblogs.com/jerrywang-blogs/p/14355734.html