AcWing 789. 数的范围
原题链接
简单
作者:
ycstar
,
2024-12-25 11:05:52
,
所有人可见
,
阅读 2
JS实现
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let inputArr = [];
let n, m;
let q = [];
rl.on("line", function (line) {
inputArr.push(line.trim());
// 第一行输入 n 和 m
if (inputArr.length === 1) {
[n, m] = inputArr[0].split(" ").map(Number);
}
// 第二行输入数组
else if (inputArr.length === 2) {
q = inputArr[1].split(" ").map(Number);
}
// 处理每个查询
else if (inputArr.length === 2 + m) {
// 处理所有查询
for (let i = 2; i < inputArr.length; i++) {
const x = Number(inputArr[i]);
console.log(findRange(q, x));
}
rl.close();
}
});
function findRange(arr, x) {
const len = arr.length;
// 查找左边界: >=x的最小值,就必然是 等于x的最左侧位置
let l = 0, r = len - 1;
while (l < r) {
const mid = l + ((r - l) >> 1);
// 如果arr[mid] >= x,说明 [mid, r]都>=x,而 我们要找的是最小的>=x的位置, 所以 右区间需要收缩
if (arr[mid] >= x) r = mid;
// 如果 arr[mid] < x,说明 [l, mid]都<x,不是我们所需要的,所以左区间向右扩增
else l = mid + 1;
}
// 如果没找到目标值
if (arr[l] !== x) {
return "-1 -1";
}
// 记录左边界
const resL = l;
// 查找右边界: <=x的最大值,就必然是 等于x的最右侧位置
l = 0; r = len - 1;
while (l < r) {
// 易错点: 注意l===mid收缩情况需要向上+1再取整
const mid = l + ((r - l + 1) >> 1);
// 如果arr[mid] <= x,说明 [l, mid]都<=x,而 我们要找的是最大的<=x的位置, 所以 左区间需要扩增
if (arr[mid] <= x) l = mid;
// 如果 arr[mid] > x,说明 [mid, r]都>x,不是我们所需要的, 所以 右区间需要收缩
else r = mid - 1;
}
// 返回结果
return `${resL} ${l}`;
}