Educational Codeforces Round 112 (Rated for Div. 2)(补题)

Posted 佐鼬Jun

tags:

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

B. Two Tables


题意: 给定一个W*H的矩形,在里面有一个蓝色桌子,坐标(左右顶点)(x1,y1)(x2,y2),然后还要在里面放一个红色桌子,要想放开红色桌子,问你蓝色桌子移动的最小距离。
思路: 只需要单一的上下左右移动即可,因为蓝色方块向单一方向移动,对另一个方向是没有贡献的(也可以理解为,因为蓝色方块周边的区域总是有长或者宽是和W或H是一样的,所以就不用再动它了)
知道只用单一移动的话,就把所有情况讨论出来就行了,上下左右移动的最小值取出来就行

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int W, H;
int x1, y1, x2, y2;
int ww, hh;
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int ax, ay, bx, by;
        int dis = inf;
        scanf("%d%d", &W, &H);
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        scanf("%d%d", &ww, &hh);
        ax = max(0, ww - x1);  //向右移动距离
        ay = max(0, hh - y1);  //向上移动距离
        //再没越界的情况下,取移动最小值
        if (ax + x2 <= W) dis = min(dis, ax);
        if (ay + y2 <= H) dis = min(dis, ay);
        bx = max(0, x2 - (W - ww));  //向左移动
        by = max(0, y2 - (H - hh));  //向下移动
        //在没越界的情况下取移动最小值
        if (x1 - bx >= 0) dis = min(dis, bx);
        if (y1 - by >= 0) dis = min(dis, by);
        //如果没更新过说明,移动越界了
        if (dis == inf)
            puts("-1");
        else
            printf("%.9lf\\n", (double)dis);
    }
    return 0;
}

C. Coin Rows



题意: 有2*n的矩阵,矩阵里有相应的点数,游戏得分为Bob得分,Alice先走,Alice想让Bob得分最小,Bob想得分最多,双方都进行最优策略,那么游戏结束时,得分为多少(一开始理解错题意了,一维Alice想让自己得分最少,想了半天没想明白)
思路: 对于Bob来说,只有两种方案,要么向右走最后向下走,要么向下走一个然后再一直向右走。
证: 对于Alice来说,Alice可以走的方案,只有下面三种图案

那么对于Bob来说,Alice如果走前两种方案,那么Bob只要走相反图案路线就行,如果是第三种,对于Bob只能吃到左下或者右上的分数,所以只要比较左下或右上哪个分数大,就抄那个路线走。
例如,右上角分数总和大,那就Bob一直向右走在向下走就行。
所以,综上所述,无论是那种情况,Bob都只能走两种方案,就是思路里写的。
此时就提前算出每种情况的左下角的总值和右上角的总值
也就是前缀和和后缀和的
Alice要让Bob分数最小化,也就是说让Bob选择的方案是Bob所有最好方案的最小值(就是只能让Bob选这条路走)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
#define inf 0x3f3f3f3f
int a[N], b[N];
int sum1[N], sum2[N];
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        for (int j = 1; j <= n; j++) {
            scanf("%d", &b[j]);
            b[j] += b[j - 1];
        }
        for (int i = n; i >= 1; i--) {
            a[i] += a[i + 1];
        }
        int res = inf;
        //枚举Alice从哪个点开始向下走
        for (int i = 1; i <= n; i++) {
            res = min({res, max(a[i + 1], b[i - 1])});
        }
        printf("%d\\n", res);
    }
    return 0;
}

D. Say No to Palindromes



题意: 定义美丽字符串为,其子串没有长度大于等于2的回文子串,只要没有,就是美丽字符串。
题目中字符串只有abc组成
现在m次查询,问你截取 [ l , r ] [l,r] [l,r]的字符串,问你把他变成美丽字符串的最小操作数,并输出。
思路: 一个字符串的子串想要不回文
拿开头是a举例,第二个只能放‘b’/‘c’,此时放b,那么第三个只能放‘c’,第四个只能放‘a’,…一旦不这样放,就会出现回文。
所以就形成了abcabcabc循环的串
一共有六种循环串
abc,acb,bac,bca,cab,cba
只要那 [ l , r ] [l,r] [l,r]的串与这六种循环串进行对比,看不同单字符个数,不同的就是要操作的个数,最终取最小值就行。
为降低时间复杂度,可以利用前缀和,提前预处理出来与六种循环串不同字符的个数,最终直接sum[l]-sum[r-1]就行
对于 l = r 和 l + 1 = r l=r和l+1=r l=rl+1=r特判就行

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define inf 0x3f3f3f3f
char s[N];
int n, m;
int sum[N][6];
char p[N][6];

int main() {
    scanf("%d%d", &n, &m);
    scanf("%s", s + 1);
    for (int i = 0; i < 6; i++) {
        char x = 'a' + i % 3;
        for (int j = 1; j <= n; j++) {
            p[j][i] = x;
            if (i > 2) {
                x++;
                if (x == 'd') x = 'a';
            } else {
                if (x == 'a')
                    x = 'c';
                else
                    x--;
            }
        }
        for (int j = 1; j <= n; j++) {
            sum[j][i] = sum[j - 1][i] + (s[j] != p[j][i]);
        }
    }
    while (m--) {
        int l, r;
        scanf("%d%d", &l, &r);
        if (l == r)
            puts("0");
        else if (l + 1 == r) {
            if (s[l] != s[r])
                puts("0");
            else
                puts("1");
        } else {
            int res = inf;
            for (int i = 0; i < 6; i++) {
                res = min(res, sum[r][i] - sum[l - 1][i]);
            }
            printf("%d\\n", res);
        }
    }
    return 0;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

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

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27