题目描述
难度分:1400
输入n,k(1≤k≤n≤2×105),q(1≤q≤2×105)。
然后输入n个recipe,每个recipe输入两个数L,R(1≤L≤R≤2×105),表示冲一杯咖啡的推荐温度范围为[L,R]。
定义一个整数温度t是可接受的,如果t包含在至少k个recipe的推荐温度范围内。
然后输入q个询问,每个询问输入两个数a,b(1≤a≤b≤2×105),输出[a,b]内有多少个温度是可接受的,每行一个答案。
输入样例1
3 2 4
91 94
92 97
97 99
92 94
93 97
95 96
90 100
输出样例1
3
3
0
4
输入样例2
2 1 1
1 1
200000 200000
90 100
输出样例2
0
算法
差分数组+二分查找
构建一个差分数组delta,在读入每个recipe的推荐温度区间[L,R]时,在delta[L]上加一,在delta[R+1]上减一,就相当于整个区间[L,R]上都是当前recipe所推荐的温度。
接下来遍历所有温度t∈[1,2×105],计算delta的前缀和,加入遍历到t温度时前缀和大于等于k,说明这个温度有至少k个recipe推荐,是一个可接受的温度,将其放入到数组cands中。
最后在读入q个询问时,就只需要二分查找确定cands中在[a,b]区间中的元素有多少个就可以了。
复杂度分析
时间复杂度
构建差分数组delta的时间复杂度为O(n)。获得cands数组需要遍历一遍delta数组,时间复杂度也是O(n)。q次询问每次都需要在cands数组中进行两次二分查找,时间复杂度是O(log2n)的,因此整体时间复杂度为O(qlog2n)。综上,整个算法的时间复杂度为O(n+qlog2n)。
空间复杂度
空间瓶颈在于差分数组delta和可接受温度的数组cands,两者的规模都是O(n)的,因此算法的额外空间复杂度为O(n)。
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 200010;
int n, k, q, l, r, a, b, delta[N];
int main() {
scanf("%d%d%d", &n, &k, &q);
for(int i = 1; i <= n; i++) {
scanf("%d%d", &l, &r);
delta[l]++;
delta[r + 1]--;
}
vector<int> cands;
int presum = 0;
for(int i = 1; i <= N - 10; i++) {
presum += delta[i];
if(presum >= k) cands.push_back(i);
}
for(int i = 1; i <= q; i++) {
scanf("%d%d", &a, &b);
int lb = lower_bound(cands.begin(), cands.end(), a) - cands.end();
int ub = upper_bound(cands.begin(), cands.end(), b) - cands.end();
printf("%d\n", ub - lb);
}
return 0;
}