Karen and Coffee题解

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

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
#include
#include
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     {
        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     {
        scanf("%d%d",&a,&b);
        printf("%d\n",sum[b]-sum[a-1]);
    }
    return 0;
}

你可能感兴趣的:(算法)