A. Karen and Morning
传送门:http://codeforces.com/contest/816/problem/A
水题,参考程序如下:
#include <stdio.h> int main(void) { int h, m, H, M; scanf("%d:%d", &h, &m); for (int i = 0; i <= 60 * 24; i++) { H = (h + (m + i) / 60) % 24; H = (m + i) % 60; if (H / 10 == M % 10 && H % 10 == M / 10) { printf("%d\n", i); break; } } return 0; }
B. Karen and Coffee
传送门:http://codeforces.com/contest/816/problem/B
本题是一个数学问题——区间统计。
给定n个整数区间,第i个区间为[li..ri]。定义数轴上一个整数点的覆盖重数为给定区间中,包含该整数的区间个数。
再给出q次查询,第j次的查询区间为[aj..bj],查询内容为区间[aj..bj]中覆盖重数至少为k的整数点的个数。
最直观的解法是直接构造覆盖重数数组c[]:c[]初始化为0,对每一个i,将c[li..ri]++;查询时,对每一个j,统计c[aj..bj]≥k的个数即可。这个记录与查询的时间复杂度均比较高,因此需要在此基础上建立一个优化方案:自左向右的计数。
计算覆盖重数数组c[]的简单方法:
a.c[]初始化为0;
b.对于每一个i,c[li]++,c[ri+1]--;
c.自左向右计数:c[a]+=c[a-1]。
如此,记录数据的复杂度为线性的:O(n+MAX_VAL)。
之后统计c[]≥k的整数点个数:直接统计的时间复杂度较高,因此可以考虑构造另一个数组cnt[]:对每一个a,cnt[a]为c[0..a]≥k的个数。因此,对于第j次查询,c[aj..bj]≥k的个数为cnt[bj]-cnt[aj-1]。
计算数组cnt[]的简单方法:
a.对于每一个0≤a≤MAX_VAL,若c[a]≥k,则cnt[a]=1,否则cnt[a]=0;
b.自左向右计数:cnt[a]+=cnt[a-1]。
程序实现上,可以使用一个数组完成操作。参考程序如下:
#include <stdio.h> #define MAX_VAL 200001 int c[MAX_VAL]; int main(void) { int n, k, q; scanf("%d%d%d", &n, &k, &q); for (int i = 0; i < n; i++) { int l, r; scanf("%d%d", &l, &r); c[l]++; c[r + 1]--; } for (int i = 1; i < MAX_VAL; i++) c[i] += c[i - 1]; for (int i = 0; i < MAX_VAL; i++) c[i] = c[i] >= k? 1: 0; for (int i = 1; i < MAX_VAL; i++) c[i] += c[i - 1]; while (q--) { int a, b; scanf("%d%d", &a, &b); printf("%d\n", c[b] - c[a - 1]); } return 0; }
原文:http://www.cnblogs.com/siuginhung/p/7745669.html