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;} elsecur = 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;elsel = mid;}if (a[l][1] < a[i][0])f[i] = f[l] + 1;elsef[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);}}
