P1712 [NOI2016] 区间 题解
思考
我们考虑枚举最长的长度.
然后假设我们目前最长的长度为\(len_{max}\),那么我们就要找最大的\(len_{min}\),使得存在一个点,使得至少有\(m\)个长度在\([len_{min},len_{max}]\)中的线段个将这个点覆盖.
覆盖可以使用线段树维护.
那么我们枚举长度的时间复杂度是\(O(n)\) 的,我们枚举最小长度的复杂度是\(O(n)\)的,对于每个线段使用线段树维护区间覆盖的复杂度是\(O(nlogn)\)的.
那么我们总的复杂度就是\(O(n(n+nlogn))\) 的.这显然太大了.
我们发现,在我们枚举\(len_{max}\)的过程中,\(len_{min}\)单调不下降.
那么我们考虑使用双指针优化.
我们维护双指针\(l,r\)代表最短长度和最长的长度,不过注意枚举的要是离散的.
然后我们考虑怎么实现判断\(l\)的增加.
问题就是判断\(l\)增加后区间最大端点覆盖会不会下降到小于\(m\).
显然,我们不能暴力的删去区间,然后恢复,那么我们就无法保证每个线段只会在线段树上删除一次.
我们考虑不恢复.
那么我们设当前实际允许的\(len_{min}\)和线段树应用的\(len_{min}\) 然后显然这两个最多差 \(1\),然后如果发现删除后不合法那就不删除,直接确定现在\(len_{max}\)的答案.
然后我们每次在尝试缩小的时候,我们先看看是否已经缩小过了,诺已经缩小过了则直接查询答案,否则缩小.
然后我们就保证了每个线段至多被插入删除一次

浙公网安备 33010602011771号