const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
// 问题描述:计算公开招聘活动所需的最少面试官数量
// 输入参数:
// - m: 每个面试官最多可以面试的人数限制
// - n: 总共需要进行的面试场次
// - arr: 面试时间区间数组,每个元素为 [start, end] 表示面试的开始和结束时间
// 核心算法思路:
// 1. 首先对所有面试时间区间按开始时间排序
// 2. 检查相邻区间是否存在时间重叠
// 3. 对于重叠的区间,需要额外的面试官
// 4. 最后根据重叠情况和每个面试官的面试次数限制(m)计算所需面试官总数
void (async function () {
// 读取输入数据
// m: 每个面试官的最大面试次数限制
const m = Number(await readline());
// n: 总面试场次
const n = Number(await readline());
// 读取所有面试时间区间
// 每个区间包含两个数字:开始时间和结束时间
const arr = [];
for (let i = 0; i < n; i++) {
arr.push((await readline()).split(" ").map(Number));
}
// 初始化变量
let res = 1; // 最少需要1名面试官
let komu = []; // 用于存储重叠的面试区间索引对
// 对面试时间区间进行排序
// 优先按开始时间升序排序,如果开始时间相同,则按结束时间升序排序
arr.sort((a, b) => {
if (a[0] == b[0]) return a[1] - b[1];
else return a[0] - b[0];
});
// 检测时间重叠
// 遍历排序后的区间,检查相邻区间是否存在重叠
for (let i = 1; i < arr.length; i++) {
// 如果当前区间的开始时间早于前一个区间的结束时间,说明存在重叠
if (arr[i][0] < arr[i - 1][1]) {
res++; // 需要增加一名面试官
komu.push([i - 1, i]); // 记录重叠的区间索引对
}
}
// 处理重叠区间
const flatKomu = komu.flat(); // 将重叠区间数组扁平化
const komuVal = new Set(flatKomu).size; // 计算重叠区间的实际数量(去重)
// 计算所需面试官数量
if (komuVal == 0) {
// 如果没有重叠区间,直接根据总场次和面试次数限制计算
// 使用向上取整:n/m
return console.log(n % m == 0 ? n / m : Math.floor(n / m) + 1);
} else {
// 存在重叠区间的情况
// 计算除去重叠区间后还需要处理的面试场次
const needVal = n - komuVal * (m - 1);
if (needVal <= 0) {
// 如果不需要额外处理,直接返回当前面试官数量
return console.log(res);
} else {
// 需要额外的面试官来处理剩余场次
// 使用向上取整计算额外需要的面试官数量
res += needVal % m == 0 ? needVal / m : Math.floor(needVal / m) + 1;
return console.log(res);
}
}
})();
// 示例说明:
// 假设输入:
// m = 2(每个面试官最多面试2人)
// n = 3(总共3场面试)
// 面试时间区间:[1,2], [2,3], [1,3]
//
// 处理过程:
// 1. 首先对时间区间排序
// 2. 检测到[1,2]和[1,3]有重叠,需要2名面试官
// 3. 考虑每个面试官的面试次数限制(m=2)
// 4. 最终计算得出所需的最少面试官数量