Codeforces 816A/B

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;
        M = (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.对于每一个ic[li]++c[ri+1]--

c.自左向右计数:c[a]+=c[a-1]。

如此,记录数据的复杂度为线性的:O(n+MAX_VAL)。

之后统计c[]≥k的整数点个数:直接统计的时间复杂度较高,因此可以考虑构造另一个数组cnt[]:对每一个acnt[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;
}

 

posted on 2017-10-27 23:39  SiuGinHung  阅读(274)  评论(0编辑  收藏  举报

导航