题目描述
FJ为他的奶牛们建造了一个游泳池,FJ认为这将有助于他们放松身心以及生产更多牛奶。
为了确保奶牛们的安全,FJ雇佣了N头牛,作为泳池的救生员,每一个救生员在一天内都会有一定的事情,并且这些事情都会覆盖一天内的一段时间。为了简单起见,泳池从时间t=0时开门,直到时间t=1000000000关门,所以每个事情都可以用两个整数来描述,给出奶牛救生员开始以及结束事情的时间。例如,一个救生员在时间t=4时开始事情并且在时间t=7时结束事情,那么这件事情就覆盖了3个单位时间。(注意:结束时间是“点”的时间)
不幸的是,FJ多雇佣了一名的救生员,但他没有足够的资金来雇佣这些救生员。因此他必须解雇一名救生员,求可以覆盖剩余救生员的轮班时间的最大总量是多少?如果当时至少有一名救生员的事情已经开始,则这个时段被覆盖。
输入格式
输入的第一行包括一个整数N(1≤N≤100000)。接下来N行中,每行告诉了我们一个救生员在0~10000000000范围内的开始以及结束时间。所有的结束时间都是不同的。不同的救生员的事情覆盖的时间可能会重叠。
输出格式
如果FJ解雇一名救生员仍能覆盖的最大时间。
因为坐标的范围很大,所以我们需要离散化一下
我们可以把问题转化一下,转化成,我们要找一个救生员,在他在的时间段内,他一个人独自在的时间最小(好绕嘴啊)
这个问题可以用差分+线段树(树状数组)解决
我们离散化后建立差分数组cfcfcf
对于一个看守区间为[l,r][l,r][l,r]的救生员,我们把CFl+1_l+1l+1,CFr−1_r-1r−1,注意这里不是r+1r+1r+1的位置-1,因为离散化之后每个值都相当于他区间的左端点了
差分完之后我们从左往右扫一遍,把每一个只有一个人的点加上他这个点所代表的长度存到线段树(树状数组)里面,对于每一个救生员,他单独存在的时间就是线段树(树状数组)中这一区间的和
然后再求一下总共用的时间就可以了
代码(线段树):
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
# include <stack>
# include <vector>
# include <set>
# include <map>