AcWing 1343. 挤牛奶 区间合并or差分 C++

题目

每天早上 5  点,三名农夫去牛场给奶牛们挤奶。

现在从 5 点开始按秒计时,第一名农夫在第 300 秒开始给牛挤奶,并在第 1000 秒停止挤奶。

第二名农夫在第 700秒开始给牛挤奶,并在第 1200 秒停止挤奶。

第三名农夫在第 1500秒开始给牛挤奶,并在第 2100  秒停止挤奶。

从开始挤奶到挤奶完全结束,这一期间,至少存在一名农夫正在挤奶的连续时间段的长度最长为 900 秒(第 300  秒至第 1200  秒),完全没有任何农夫在挤奶的连续时间段的长度最长为 300 秒(第 1200 秒至第 1500  秒)。

现在给你 N 名农夫挤 N 头奶牛的工作时间表,请你求出:

1、至少存在一名农夫正在挤奶的连续时间段的最长长度。

2、没有任何农夫在挤奶的连续时间段的最长长度。

注意:本题中给出的所有时间均为时刻(时间点),因此在本题中挤奶区间 [100,200] 和[201,300] 中间会有长度为 1 秒的间歇时间。

输入格式

第一行包含整数 N  ,表示农夫数量。

接下来 N  行,每行包含两个非负整数 l,r  ,表示农夫挤奶的开始时刻和结束时刻。

输出格式

共一行,包含两个整数,分别表示最长连续挤奶时间以及最长连续无人挤奶时间。

数据范围

1≤N≤5000  , 0≤l≤r≤106 

输入样例:

3

300 1000

700 1200

1500 2100

输出样例:

900 300

算法一(区间合并)

算法思想

AcWing 1343. 挤牛奶 区间合并or差分 C++_第1张图片

完整代码

#include
using namespace std;
const int N=5010;
typedef pair PII;//存l,r
PII seg[N];
int main()
{
	int n;
	cin>>n;
	for(int i=0;i>seg[i].first>>seg[i].second;
	}
	sort(seg,seg+n);//将区域进行排序(先按first,first相同再按second),便于后续合并 
	int res1=0;//最长连续挤奶时间 
	int res2=0;//最长连续没有挤奶时间 
	int st=seg[0].first;//第一个区域的起点 
	int ed=seg[0].second;//第一个区域的终点 
	for(int i=1;i

 算法二(差分)

算法思想

//差分算法

//原序列a[],差分数组d[i]=a[i]-a[i-1]; 

//原序列a[]在区间[l,r]上加上元素k时,只需将 d[l]+=k,d[r+1]-=k;

//最后求前缀和,还原出更新之后原序列 ;

 完整代码

//注意区间问题 
//900秒(第300秒至第1200秒),如果是[l,r],则应该是r-l+1=901秒;
//300秒(第1200秒至第1500秒),如果是[l,r],则应该是r-l+1=301秒;
//所以,应该是左闭右开区间[l,r),即r-l秒; 
#include
using namespace std;
const int N=1000010;
int d[N];
int main()
{
	int n;
	cin>>n;
	int R=0;//求右区间 
	int L=1e6+10;//求左区间 
	while(n--)
	{
		int l,r;
		cin>>l>>r;
		R=max(R,r);
		L=min(L,l);
		d[l]+=1;//因为是左闭右开区间,所以实际的区间应是[l,r-1]; 
		d[r]-=1;
	}
	for(int i=1;i<=R-1;i++)
	{
		d[i]+=d[i-1];
	}
	int res1=0;//最长连续挤奶时间 
	int res2=0;//最长连续没有挤奶时间 
	int ans1=0;
	int ans2=0;
	for(int i=L;i<=R-1;i++)
	{
		if(d[i]!=0)
		{
			ans1++;
			res1=max(res1,ans1);
		}else{
			ans1=0;
		}
	}
	for(int i=L;i<=R-1;i++)
	{
		if(d[i]==0)
		{
			ans2++;
			res2=max(res2,ans2);
		}else{
			ans2=0;
		}
	}
	cout<

你可能感兴趣的:(AcWing,c++,算法,数据结构)