Codeforces Round #614 (Div. 2)

Posted kisekipurin2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #614 (Div. 2)相关的知识,希望对你有一定的参考价值。

21:35刚刚降落广州白云机场,在手机上打了个Python刷个场次,顺便掉个蓝色献祭一下这个学期的考试分数。

A - ConneR and the A.R.C. Markland-N

题意:找不出现在k个给定数字之中的,值域在[1,n]的离s最近的数字的距离。保证k<n。

题解:

1.常数比较低的做法:先排序,然后看看s是不是在k个数字里面,不在的话直接就0,否则一定在里面。然后给ans赋值初始值,取k个数字的两端。然后遍历每个数字,只要它和上一个数字不连续,那么中间可以贪心一个位置(然后break掉,但是懒)。

int a[1005];
void test_case() {
    int n, s, k;
    scanf("%d%d%d", &n, &s, &k);
    for(int i = 1; i <= k; ++i)
        scanf("%d", &a[i]);
    sort(a + 1, a + 1 + k);
    int pos = 0;
    for(int i = 1; i <= k; ++i) {
        if(a[i] == s) {
            pos = i;
            break;
        }
    }
    if(pos == 0) {
        puts("0");
        return;
    }
    int ans = INF;
    if(a[1] != 1)
        ans = s - (a[1] - 1);
    if(a[k] != n)
        ans = min(ans, a[k] + 1 - s);
    for(int i = pos - 1; i >= 1; --i) {
        if(a[i] == a[i + 1] - 1)
            continue;
        ans = min(ans, s - (a[i + 1] - 1));
    }
    for(int i = pos + 1; i <= k; ++i) {
        if(a[i] == a[i - 1] + 1)
            continue;
        ans = min(ans, a[i - 1] + 1 - s);
    }
    printf("%d
", ans);
}

2.因为删除至多k个数字,那么在s的附近k+1个不越界的数字全部插进set,然后遍历这个数组把不要的删掉,找前驱和后继。多组数据记得clear()掉。

set<int> _set;
void test_case() {
    _set.clear();
    int n, s, k;
    scanf("%d%d%d", &n, &s, &k);
    int F = max(1, s - k - 2);
    int C = min(n, s + k + 2);
    for(int i = F; i <= C; ++i)
        _set.insert(i);
    for(int i = 1; i <= k; ++i) {
        int ai;
        scanf("%d", &ai);
        _set.erase(ai);
    }
    auto it = _set.lower_bound(s);
    int ans = INF;
    if(it != _set.end())
        ans = *it - s;
    if(it != _set.begin()) {
        --it;
        ans = min(ans, s - *it);
    }
    printf("%d
", ans);
}

B - JOE is on TV!

题意:有s个人,每次可以搞掉其中的t个,获得t/s的分数,求把s个人全部搞掉得到的最多的分数。

题解:由不等式:

[frac{t}{s}+frac{1}{s-1}geqfrac{t+1}{s}]

以及数学归纳法得到。

这道题不卡精度,随便过,怎么暴力怎么来。

void test_case() {
    int n;
    scanf("%d", &n);
    double ans = 0;
    for(int i = 1; i <= n; ++i)
        ans += 1.0 / i;
    printf("%.8f
", ans);
}

C - NEKO‘s Maze Game

题意:有一个2行n列的棋盘格迷宫,要求从(1,1)走到(2,n),有q次修改,每次修改把某个点(r,c)的可行/不可行状态翻转,问每次修改后还能不能从起点到达终点。

题解:这个形式,只有两行,很明显满足无后效性。首先判断是不是有同一列的两个都被不可行,这个可以O(1)维护出来,否则导致出现No的就必须是一个斜方向的格,这个也可以O(1)维护出来。

int sta[2][100005];
int vis[2][100005][3];
int cnt;

void test_case() {
    int n, q;
    scanf("%d%d", &n, &q);
    while(q--) {
        int r, c;
        scanf("%d%d", &r, &c);
        --r;
        if(sta[r][c] == 0) {
            sta[r][c] = 1;
            vis[1 - r][c + 1][0] = 1;
            vis[1 - r][c][1] = 1;
            vis[1 - r][c - 1][2] = 1;
            if(vis[1 - r][c + 1][0] && sta[1 - r][c + 1])
                ++cnt;
            if(vis[1 - r][c][1] && sta[1 - r][c])
                ++cnt;
            if(vis[1 - r][c - 1][2] && sta[1 - r][c - 1])
                ++cnt;
        } else {
            if(vis[1 - r][c + 1][0] && sta[1 - r][c + 1])
                --cnt;
            if(vis[1 - r][c][1] && sta[1 - r][c])
                --cnt;
            if(vis[1 - r][c - 1][2] && sta[1 - r][c - 1])
                --cnt;
            sta[r][c] = 0;
            vis[1 - r][c + 1][0] = 0;
            vis[1 - r][c][1] = 0;
            vis[1 - r][c - 1][2] = 0;
        }
        if(cnt)
            puts("No");
        else
            puts("Yes");
    }
}

以上是关于Codeforces Round #614 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #614 (Div. 2)

Codeforces Round #614 (Div. 2)

Codeforces Round #614 选讲

Codeforces Round #614 (Div. 2)

Codeforces Round #614 (Div. 2)

Codeforces Round #614 (Div. 2) A-E简要题解