这个题目用了二分的方法去优化时间复杂度
首先根据题目可以得到的是--线段中点在区间内才算是被区间覆盖
线段中点在线段内 ⇔ L ≤ (l+r)/2 ≤ R
然后可以转化为2L ≤ l+r ≤ 2R
cpp
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100010;
int mid2[N]; // 存储每个线段中点的2倍值
int n, m;
// 找到第一个 >= x 的位置
int find_left(int x) {
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (mid2[mid] >= x) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l; // l是第一个>=x的位置
}
// 找到第一个 > x 的位置
int find_right(int x) {
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (mid2[mid] > x) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l; // l是第一个>x的位置
}
int main() {
cin >> n >> m;
for(int i = 0; i < n; i++) {
int l, r;
cin >> l >> r;
mid2[i] = l + r; // 中点的2倍
}
// 排序
sort(mid2, mid2 + n);
// 处理m个查询
for(int k = 0; k < m; k++) {
int L, R;
cin >> L >> R;
// 自己实现二分查找
int left = find_left(2 * L); // 第一个 >= 2L 的位置
int right = find_right(2 * R); // 第一个 > 2R 的位置
cout << (right - left) << endl;
}
return 0;
}