好像接触过不少区间覆盖类的问题了,写个博客小结一下。
1,求最大覆盖次数
问题描述:相当于给你一些区间,每次给这些区间内的点值都加一(初始都为0),然后问最大的值是多少。(也就是单点的最大覆盖次数)
解决思路:显然树状数组可以很好地解决,复杂度nlogn,显得有些大材小用了。现在有一个好写复杂度还低一点的办法:把所有区间的左端点标为1,右端点标为-1,再从头到尾遍历一遍加上当前点的值,维护ans为最大值即可。
tips:为了防止一个区间的右端点和另一个的左端点重合导致答案错误,采取r++操作,可以证明不会影响结果。
代码实现:
#include
#include
#include
#include
#include
#include
#include
#include
#include
2,求最多不相交区间
问题描述:经典例题:一个人要参加一些会议,给你这些会议的开始和结束时间,问你他最多能参加多少会议。
解题思路:贪心的思想做。贪心策略:哪个越早结束就先参加哪个。结构体排序,按结束时间排,再贪心遍历求解即可。
代码实现:
#include
#include
#include
#include
#include
#include
#include
#include
#include
例题:略略略
3,求被覆盖i次的点的个数
问题描述:给你n个区间,分别求出被覆盖1-n次的点的个数
解题思路:把端点从小到大排个序,左端点标个1,右端点标个-1(实际上是右端点的后面一位,避免左端点和另一个的右端点重合情况的干扰),从左到右扫一遍,这样就能很方便地求出不同区间覆盖次数的值。

如图,给两个区间[1,7], [5, 12],用now记录当前我们加的前缀和,我们在遍历到5的时候,有cnt[1] += (5-3),(now ==1)遍历到8的时候,cnt[2] += (8 - 5),(now == 2)(其实这里是区间[5,7]的贡献,这也能解释为什么在标记的时候标记右端点的后一位),再遍历到13,cnt[1] += (13 - 8),(now == 1)。这样就能很好的完成记录。
代码:(用map显然更方便一点)
#include
#include
#include
#include
#include
#include
#include
#include
#include
例题:Cross Fire!!!
4,求最少的能覆盖区间的区间数
大意:给一个区间[L, R],再给一些[l[i], r[i]],求用这些区间覆盖[L, R]的最少数目
解决思路:贪心解决。把这些区间以左端点进行排序,先选择第一个区间,之后的贪心策略就是选择在可选范围内的,选择右端点最大的区间。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
(此代码可 AC POJ2376)http://poj.org/problem?id=2376
5,求一段区间覆盖了多少个其他的区间
大意:给你一些区间,有一些询问,每次询问给一个区间,输出这个区间覆盖了多少区间
解题思路:用二维前缀和来做。一个区间用a[l, r]来表示。询问的时候就相当于求[l, l] 到 [r, r]这个矩形中的元素数目
即sum[r][r] - sum[r][l-1] - sum[l-1][r] + sum[l-1][l-1]
#include
#include
例题:D - AtCoder Express 2