






















给定 ( N ) 个闭区间 ([a_i, b_i]),将这些区间分成若干组,要求每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。输出最小组数。
第一行包含整数 ( N ),表示区间数。
接下来 ( N ) 行,每行包含两个整数 ( a_i, b_i ),表示一个区间的两个端点。
输出一个整数,表示最小组数。
( 1 \leq N \leq 10^5 ),( -10^9 \leq a_i \leq b_i \leq 10^9 )
3
-1 1
2 4
3 5
2
核心要求:组内区间无交集(含端点),组数最少。
可以类比为「活动安排问题」:有若干活动,每个活动有开始和结束时间,同一教室不能安排有交集的活动,求最少需要的教室数量(教室数即组数)。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
struct Node {
int l, r;
// 按左端点升序排序
const bool operator<(const Node &b) const {
return l < b.l;
}
} range[N];
int main() {
cin >> n;
for (int i = 0; i < n; i++) cin >> range[i].l >> range[i].r;
sort(range, range + n);
// 小根堆:存储各组的右端点,堆顶为最小右端点
priority_queue<int, vector<int>, greater<int>> heap;
for (int i = 0; i < n; i++) {
auto t = range[i];
// 堆为空或当前区间与所有组有交集,新开一组
if (heap.empty() || heap.top() >= t.l) {
heap.push(t.r);
} else {
// 可放入右端点最小的组,更新该组右端点
heap.pop();
heap.push(t.r);
}
}
cout << heap.size() << endl;
return 0;
}
按右端点排序会导致分组结果错误,举反例说明:
假设有 4 个区间:([1,5])、([2,3])、([4,6])、([7,8])。
原因:按右端点排序会破坏区间左端点的递增性,导致无法合理利用组内空间,进而多开不必要的组。而按左端点排序能保证后续区间的左端点不小于之前的区间,确保贪心策略的有效性。
类似题目: https://www.luogu.com.cn/problem/U422228
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
static class Interval{
private int l;
private int r;
public Interval(int l, int r) {
this.l = l;
this.r = r;
}
}
public static int minMeetingRooms(Interval[] intervals) {
if (intervals == null || intervals.length == 0) {
return 0;
}
// 按会议开始时间升序排序
Arrays.sort(intervals, Comparator.comparingInt(o -> o.l));
// 最小堆:维护当前各会议室的“最早结束时间”
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// 第一个会议占用一个会议室
minHeap.offer(intervals[0].r);
for (int i = 1; i < intervals.length; i++) {
int start = intervals[i].l;
int end = intervals[i].r;
// 如果当前会议开始时,最早结束的会议室已空闲(注意:>= 表示可复用)
if (start >= minHeap.peek()) {
minHeap.poll(); // 释放该会议室
}
// 当前会议占用一个会议室(无论是复用还是新开)
minHeap.offer(end);
}
// 堆的大小 = 同时进行的最大会议数 = 最少会议室数
return minHeap.size();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Interval[] intervals = new Interval[n];
for (int i = 0; i < n; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
intervals[i] = new Interval(a, b);
}
System.out.println(minMeetingRooms(intervals));
}
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。