​B - Karen and Coffee CodeForces - 816B (思维)​

题意:意思是有个n配方,每个配方给出一个温度范围a-b表示这个范围的coffe最好喝。给出q个查询a-b,问a-b范围内的温度里面有多少温度值满足有k个配方说他是合适温度。换句话说就是:给出n个范围,问查询中的范围内被覆盖次数大于k的数量。

思路:这个肯定暴力是不行的,一开始不会,去学习了一下。知道了一个很好的用法。首先你得知道什么是前缀和(其实这题中的不难理解的)

1、用到两个数组cnt[],(cnt[i]表示温度i在n个配方中出现的次数)sum[].(sum[i]表示温度i前面一共有多少个满足大于等于k的数目)

2、不能暴力直接把每次都遍历cnt[i]++。将输入的范围a-b cnt[a]++,cnt[b+1]--;输入n个以后,遍历一遍cnt[i]+=cnt[i+1],满足条件的时候sum[i]=sum[i-1]+1,不然sum[i]=sum[i-1]。这样就能在n的复杂度直接计算出来。求结果直接sum[b]-sum[a-1]

由于之间记录是cnt[a]++,cnt[b+1]--.遍历时cnt[i]+=cnt[i-1].这就保证了到了第i个配方的范围内就开始计数+1,出了范围内有-1.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=200000+10;
int cnt[maxn],sum[maxn];
//暴力肯定超时了
int main()
{
int n,k,q,a,b;
scanf("%d%d%d",&n,&k,&q);
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for(int i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
cnt[a]++,cnt[b+1]--;
//表示从a开始处理b+1的时候就没有这个值了
//这个方法好。可以给区间计数!
}
for(int i=1;i<=maxn;i++)
{
cnt[i]+=cnt[i-1];
if(cnt[i]>=k) sum[i]=sum[i-1]+1;
else sum[i]=sum[i-1];
}
for(int i=0;i<q;i++)
{
scanf("%d%d",&a,&b);
printf("%d\n",sum[b]-sum[a-1]);
}
return 0;
}