一.题目
给定 N 个闭区间 [ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
输入格式
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示最小组数。
数据范围
1≤N≤105,
−109≤ai≤bi≤109
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
解答
思路1
将结点按照左端点排序,然后使用优先队列(小根堆)PriorityQueue存储每个点的右端点。若待测点的左端点 <= 右端点的最小值,则开新组;否则将其放入该右端点所在的组,同时更新小根堆。
//按照左端点排序
import java.io.*;
import java.util.*;
class Range implements Comparable<Range>{
public int l;
public int r;
public Range(int l, int r) {
this.l = l;
this.r = r;
}
public int compareTo(Range r) {
return this.l - r.l;
}
}
public class Main{
private static int N = 100010;
private static List<Range> list = new ArrayList<>();
//优先队列也就是小根堆:存储右端点
private static PriorityQueue<Integer> heap = new PriorityQueue<>();
public static void main(String[] args) {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int n = sc.nextInt();
while(n-- > 0)
{
int a = sc.nextInt();
int b = sc.nextInt();
list.add(new Range(a, b));
}
//排序
list.sort((e1, e2) -> e1.l - e2.l);
for(int i = 0;i < list.size();i ++)
{
Range t = list.get(i);
int l = t.l, r = t.r;
if(heap.isEmpty() || heap.peek() >= l)
{
heap.add(r); //新组
}else {
heap.poll();
heap.add(r);
}
}
System.out.println(heap.size());
}
}
思路二
求最大区间厚度的问题
有若干个活动,第i个活动开始时间和结束时间是[Si, Fi],同一个教室安排的活动时间不能重合,那么安排所有活动,至少需要多少个教室?
把所有开始时间和结束时间排序,遇到开始时间就把教室数加1,遇到结束时间则减1。峰值就是我们至少需要的教室数。
//按照左端点排序
import java.io.*;
import java.util.*;
public class Main{
private static int N = 100010;
private static int idx = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int n = sc.nextInt();
int[] num = new int[n*2];
//左端点:偶数,右端点:奇数
while(n-- > 0)
{
int a = sc.nextInt();
int b = sc.nextInt();
num[idx ++] = a*2;
num[idx ++] = b*2+1;
}
Arrays.sort(num);
int res = 1, t = 0;
for(int i = 0;i < idx;i ++)
{
if(num[i] % 2 == 0) t ++; //遇到开始+1
else t --; //遇到结束-1
res = Math.max(res, t);
}
System.out.println(res);
}
}