codeforces 816B Karen and Coffee (差分思想)

题目链接

816B Karen and Coffee

题目分析

题意:有个人在学泡咖啡,因此看了很多关于泡咖啡温度的书,得到了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;
}
codefoeces 618B Karen and Coffee
posted @ 2019-08-13 16:17  winter-bamboo  阅读(206)  评论(0编辑  收藏  举报