codeforces 816B.Karen and Coffee 解题报告

题目链接:http://codeforces.com/contest/816/problem/B

题目意思:给出 n 个recipes,第 i 个(1<= i <=n)recipes 表明 coffee 调制的推荐温度范围是 [li, ri] 之间。现在有 q 个问题,每个问题需要回答 coffee 在范围 [a, b] 之间,共有多少个数满足至少有 k 个推荐。

题目解析:这题主要是考我们对于大范围(最大200000),如何处理数据。方法是很容易想到的,但要考虑优化,即离线处理。20w * 20w,直接做是很容易超时啦~~~(我就交了好几个 TLE 了,以为不会超过2.5 秒的,看来时间评估也很重要哇,囧 )

  需要准备两个一维数组,cnt[] 和 sum[] 来处理每一个满足数 i (范围 [1, 200000]  )

  cnt[i] 数组:第 i 个数获得的推荐数

  sum[i] 数组: 前 i 个数满足 k 个推荐的前缀和。

  拿 test1 的测试数据来分析,请看下面的图

  

       所以对于 k 个提问,sum[b] - sum[a-1] 就是答案了。

  这里最巧妙之处就是cnt[i] 要怎么统计出来。如果 [li, ri] 范围的数都遍历一次,绝对会TLE的!!! 处理两个点其实就可以统计出来了,分别是 cnt[li], cnt[ri+1]。 对于每一次询问,进行:cnt[li]++, cnt[ri+1]-- 处理。然后 q 个问题之后,再统一遍历多一次,利用前一个数 cnt[i-1] 就能统计出当前数 cnt[i] 了。(这个方法我也是第一次见,厉害厉害~~~以后就会敏感点了 ^___^)

  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 2e5 + 5;
 9 int cnt[maxn];
10 int sum[maxn];
11 
12 int main()
13 {
14     #ifndef ONLINE_JUDGE
15         freopen("in.txt", "r", stdin);
16     #endif // ONLINE_JUDGE
17     int n, k, q;
18 
19     while (cin >> n >> k >> q) {
20         int l, r;
21         memset(cnt, 0, sizeof(cnt));
22         for (int i = 0; i < n; i++) {
23             scanf("%d%d", &l, &r);
24             cnt[l]++;
25             cnt[r+1]--;
26         }
27         memset(sum, 0, sizeof(sum));
28         for (int i = 1; i <= 200000; i++) {
29             cnt[i] += cnt[i-1];
30             sum[i] = (cnt[i]>=k ? sum[i-1]+1: sum[i-1]);
31         }
32         int a, b;
33         while (q--) {
34             scanf("%d%d", &a, &b);
35             printf("%d
", sum[b]-sum[a-1]);
36         }
37     }
38     return 0;
39 }
View Code
原文地址:https://www.cnblogs.com/windysai/p/7044418.html