题目链接
题目分析
题意:有个人在学泡咖啡,因此看了很多关于泡咖啡温度的书,得到了n种推荐的泡咖啡温度范围[L1,R1] ,此人将有k种做法推荐的温度记为可用温度(个人翻译),然后给出q次询问,问区间[L2,R2]内的温度,有多少个温度是可用温度(每个整数代表一个温度)

思路:一开始用的是线段树写的,不过姿势不对,TLE了,然后改过来后,发现时间比较长,就考虑一下优化的方法。
比线段树某些功能更优的算法:差分思想,在对某一区间每个位置上的数加上一个值x,并求任意位置的数的时候,时间上比线段树 O(nlogn)的复杂度更低,为O(n),空间更小,代码更短,很合适。
那么如何运用差分思想来写这个题呢?首先用O(n)的时间求出每个温度有多少种做法推荐,然后维护一个前缀和sum[i],记录区间 [1, i ] 表示的温度中有多少个温度满足条件(即有多少个温度有k种以上做法推荐),用O(n)的时间求出sum数组,sum[i] = sum[i-1] + (val[i] >= k ? 1 : 0;) ,最后查询区间[ L2,R2]有多少适合的温度时,输出 sum[R2] - sum[L2-1] 。
(不了解什么是差分的话,可以看下我的这篇博客 差分+树上差分)
代码区

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>
#define bug cout << "**********" << endl
#define show(x,y) cout<<"["<<x<<","<<y<<"] "
//#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 2e5 + 10;
int n, k, q;
int val[Max], sum[Max]; //val为差分数组,sum[i]记录区间[1,i]有多少个温度被确定为合适
int main()
{
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
while (scanf("%d%d%d", &n, &k, &q) != EOF)
{
memset(val, 0, sizeof(val));
memset(sum, 0, sizeof(sum));
for (int i = 1, l, r; i <= n;i++)
{
scanf("%d%d", &l, &r);
val[l]++;val[r + 1]--;
}
for (int i = 1;i <= 200000 ;i++)
{
val[i] += val[i - 1]; //差分数组的前缀和即为该点的值
sum[i] = sum[i-1] + (val[i] >= k ? 1 : 0);
}
for(int i = 1 ,l,r;i <= q; i ++)
{
scanf("%d%d", &l, &r);
printf("%d\n", sum[r] - sum[l-1]);
}
}
return 0;
}
