区间问题总结:
1.区间选点 && 最大不相交区间数量
在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。
输出可选取区间的最大数量。
方法:
1)按照右端点从小到大排序
2)从前往后依次枚举每个区间 for(int i=0;i<n;i++)
如果上一区间的右端点end与当前区间的左端点,无法交叉形成交集(end < a[i].l)
则当前区间的右端点作为新的end,并且计数
(区间没有交集-->更新+计数)
(区间有交集-->代表点已经覆盖到了-->不需要任何操作)
2.区间分组(组和区间问题)
将区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
方法:
1)按照左端点从小到大排序
2)从前往后依次枚举每个组/集合 for(int j=1;j<=cnt;j++)
如果所有组中存在某一组最右端点,小于当前区间的左端(没交集),则更新该组的最右端点
if(rd[j] < a[i].l)
rd[j]=a[i].r;
如果没有任何一组满足,则开启一个新组 rd[++cnt]=a[i].r;
(组和区间没有交集-->区间添加至该组-->更新组右端点)
(所有组和区间都有交集-->开启一个新的组-->更新组右端点)
3.区间覆盖
选择尽量少的区间,将指定线段区间[start,end]完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 −1。
方法:
1)按照左端点从小到大排序
2)从前往后依次枚举每个区间 for(int i=0;i<n;i++)
在所有能覆盖start的区间中,选择右端点最大的区间,区间右端点记为r。
移动线段区间的左端点start,设置为r。
for(i=j;j<n && a[j].first<=start;j++)
r=max(r,a[j].second); //找到符合条件的最右端点
每次枚举,计数器cnt加一。ans++;
直至右端点r已经超过了end,成功覆盖。start=r;