题目链接: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 }