Acwing 905. 区间选点
给定 N 个闭区间 [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 N,表示区间数。
接下来 N行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围1≤N≤105,
−109≤ai≤bi≤109
输入样例:3 -1 1 2 4 3 5
输出样例:2
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] q = new int[n][2];
for (int i = 0; i < n; i++) {
q[i][0] = sc.nextInt();
q[i][1] = sc.nextInt();
}
Arrays.sort(q, (o1, o2) -> o1[1] - o2[1]);
int cnt = 0, cur = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
if (q[i][0] > cur) {
cnt++;
cur = q[i][1];
}
}
System.out.println(cnt);
}
}
Acwing 908. 最大不相交区间数量
给定 N 个闭区间 [ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。
输出可选取区间的最大数量。
输入格式
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示可选取区间的最大数量。
数据范围1≤N≤105
−109≤ai≤bi≤109
输入样例:3 -1 1 2 4 3 5
输出样例:2
//方法一
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] q = new int[n][2];
for (int i = 0; i < n; i++) {
q[i][0] = sc.nextInt();
q[i][1] = sc.nextInt();
}
Arrays.sort(q, (o1, o2) -> o1[1] - o2[1]);
int cnt = 0, cur = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
if (q[i][0] > cur) {
cnt++;
cur = q[i][1];
}
}
System.out.println(cnt);
}
}
// 方法二
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] p = new int[n][2];
for (int i = 0; i < n; i++) {
p[i][0] = sc.nextInt();
p[i][1] = sc.nextInt();
}
int ans = 0;
Arrays.sort(p, (o1, o2) -> (o1[0] - o2[0]));
int cur = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
int a = p[i][0], b = p[i][1];
if (a > cur) {
ans++;
cur = b;
} else
cur = Math.min(cur, b);
}
System.out.println(ans);
}
}
方法3:DP的思路,类似于2008
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] a = new int[n][2];
for (int i = 0; i < n; i++) {
a[i][0] = sc.nextInt();
a[i][1] = sc.nextInt();
}
Arrays.sort(a, (o1, o2) -> (o1[1] - o2[1]));
int[] f = new int[n];
f[0] = 1;
for (int i = 1; i < n; i++) {
int l = 0, r = i;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[mid][1] >= a[i][0])
r = mid - 1;
else
l = mid;
}
if (a[l][1] < a[i][0])
f[i] = f[l] + 1;
else
f[i] = 1;
f[i] = Math.max(f[i - 1], f[i]);
}
System.out.println(f[n - 1]);
}
}
Acwing 906. 区间分组
给定 N 个闭区间 [ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
输入格式
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示最小组数。
数据范围1≤N≤105
−109≤ai≤bi≤109
输入样例:3 -1 1 2 4 3 5
输出样例:2
随便挑一个放的原因是,如果能放到其它组中,说明后面遍历的区间也能放到其他组中,效果等价
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] a = new int[n][2];
for (int i = 0; i < n; i++) {
a[i][0] = sc.nextInt();
a[i][1] = sc.nextInt();
}
Arrays.sort(a, (o1, o2) -> o1[0] - o2[0]);
PriorityQueue<Integer> q = new PriorityQueue<>();
for (int i = 0; i < n; i++) {
if (q.isEmpty() || q.peek() >= a[i][0])
q.offer(a[i][1]);
else {
q.poll();
q.offer(a[i][1]);
}
}
System.out.println(q.size());
}
}
方法2:
利用差分的思想,每添加一个区间,就将这个区间内所有数加1
前缀和就是当前区间的最少分组数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < n; i++) {
int a = sc.nextInt(), b = sc.nextInt();
map.merge(a, 1, Integer::sum);
map.merge(b + 1, -1, Integer::sum);
}
int max = 0, cnt = 0;
for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
cnt += pair.getValue();
if (max < cnt)
max = cnt;
}
System.out.println(max);
}
}
Acwing 907. 区间覆盖
给定 N 个闭区间 [ai,bi] 以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 −1。
输入格式
第一行包含两个整数 s 和 t,表示给定线段区间的两个端点。
第二行包含整数 N,表示给定区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需最少区间数。
如果无解,则输出 −1。
数据范围1≤N≤105
,−109≤ai≤bi≤109
,−109≤s≤t≤109
输入样例:1 5 3 -1 3 2 4 3 5
输出样例:2
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int st = sc.nextInt(), ed = sc.nextInt();
int n = sc.nextInt();
int[][] a = new int[n][2];
for (int i = 0; i < n; i++) {
a[i][0] = sc.nextInt();
a[i][1] = sc.nextInt();
}
Arrays.sort(a, (o1, o2) -> o1[0] - o2[0]);
int cnt = 0, cur = st;
for (int i = 0; i < n; i++) {
int j = i;
int last = cur;
while (j < n && a[j][0] <= cur) {
last = Math.max(last, a[j][1]);
j++;
}
if (last == cur)
break;
cnt++;
cur = last;
i = j - 1;
if (cur >= ed)
break;
}
if (cur >= ed) System.out.println(cnt);
else System.out.println(-1);
}
}