Codeforces Round #821 (Div. 2)

前置废话

下午的 \(Div.2\) 还是比较水的,是我想复杂了,前面简单题切的有些慢,也可能是前几分钟还没睡醒吧。。。

写下简要题面吧,要不然都不知道我在说什么


Codeforces Round #821 (Div. 2)

A. Consecutive Sum

题面

给定一个长度为 \(n\) 的序列, 最多可以进行以下操作 \(k\) 次:

选择 \(a_i\)\(a_j\)\(i \,\bmod\, k = j \,\bmod\, k\))(\(1 \le i < j \le n\)),并将其交换位置。

执行完所有操作后,你必须选择 \(k\) 个连续的元素,使这 \(k\) 个元素的总和最大。

输入:\(T\)(数据组数) \(n\ 、k\ 、 a_1 …… a_n\)

题解

对于所有同余的数 \((mod k)\)\(max\) 之后求和即可。

B. Rule of League

题面

有一个羽毛球锦标赛,有 \(n\) 名球员参加。 玩家从 \(1\)\(n\) 编号。

规则如下:玩家 1 玩家 2 玩游戏,然后获胜者和玩家 3 玩游戏,然后获胜者和玩家 4 玩游戏,以此类推。

因此,进行了 \(n-1\) 场比赛,最后一场比赛的获胜者成为冠军。

比赛中没有平局。

你想知道冠军的结果。

目前,您只知道以下信息:

每个球员要么赢了 \(x\) 场比赛,要么赢了 \(y\) 场比赛。

给定 \(n\)\(x\)\(y\),找出是否有与此信息匹配的结果。

题解

一开始想复杂了,直接上的 \(exgcd\) , 其实仔细想想就能发现:如果 \(x\)\(y\) 都不为零是不满足题意的,直接输出 \(-1\) 即可。

还有 \(x\)\(y\) 都为零是也是直接输出 \(-1\)

剩下的只有一种为零的直接模拟即可。

C. Parity Shuffle Sorting

题面

给定一个包含 \(n\) 个非负整数的数组 \(a\)。 你可以对其应用以下操作。

选择两个两个数 \(a_l\)\(a_r \ (1 \le l < r \le n)\) 。如果 \(a_l + a_r\) 是奇数: \(a_r \gets a_l\);否则:\(a_l \gets a_r\)

找到任何最多 \(n\) 个操作的序列,使 \(a\) 不递减。 可以证明,它总是可能的。 请注意,你不必尽量减少操作次数

题解

多测不清空,爆零两行泪。

观察操作,发现:奇偶性相同,后面的值赋给前面,否则前面的值赋给后面。

注意到加粗的话:意思是 我们可以乱搞了 可以将这些数变成同一个数!

具体来说:判断第一个数的奇偶性,如果是奇数(偶数同理),那么将所有的奇数变成最后一个奇数的值,再将所有偶数变成第一个奇数的值。

Code moo~~
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <set>
using namespace std;
#define int long long
#define re register int
#define pc_ putchar(' ')
#define pc_n putchar('\n')
#define Bessie signed
inline int read() {
    int A = 0, FL = 1;
    char CH = getchar();
    while(CH < '0' || CH > '9') FL = CH == '-' ? -1 : 1, CH = getchar();
    while(CH >= '0' && CH <= '9') A = (A << 3) + (A << 1) + (CH ^ '0'), CH = getchar();
    return A * FL;
}
inline void ot(int x) {
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) ot(x / 10); putchar(x % 10 | '0');
}
const int CTR = 2e5 + 7, INF = 5e5 + 7;
int T;
int n;
int a;
int x[CTR], topx, y[CTR], topy;
Bessie main() {
    T = read();
    while(T--) {
        n = read();
        //当时没清空x[1]和y[1]爆了三发
        //但是直接memset会T
        x[1] = y[1] = topx = topy = 0;
        for(re i = 1; i <= n; ++i) {
            a = read();
            if(a % 2 == 0) x[++topx] = i;
            else y[++topy] = i;
        }
        ot(n - 1),pc_n;
        if(n - 1 == 0) continue;
        if(x[1] == 1) {
            for(re i = 1; i < topx; ++i) ot(x[i]),pc_,ot(x[topx]),pc_n;
            for(re i = 1; i <= topy; ++i) ot(1),pc_,ot(y[i]),pc_n;
        }
        else if(y[1] == 1){
            for(re i = 1; i < topy; ++i) ot(y[i]),pc_,ot(y[topy]),pc_n;
            for(re i = 1; i <= topx; ++i) ot(1),pc_,ot(x[i]),pc_n;
        }
    }
    return 0;
}

D1. Zero-One (Easy Version)

题面

给定两个 \(01\) 字符串 \(a\)\(b\),长度均为 \(n\)。 你可以多次执行以下操作(可能为零)。

选择两个数 \(a_l,a_r(l<r)\)

\(a_l\) 更改为 \((1−a_l)\),并将 \(a_r\) 更改为 \((1−a_r)\)

如果 \(l+1=r\) ,则操作成本为 \(x\),否则成本为 \(y\)

你必须找到使 \(a\) 等于 \(b\) 所需的最低成本,或者输出\(-1\) \((a\) 不可能等于 \(b)\)

\(5 \le n \le 3000,1 \le y \le x \le 10^9\)

具有启发性的样例

\(in\)

4(T)

5(n) 8(x) 7(y)
01001(a)
00101(b)

5 7 2
01000
11011

7 8 3       //就是这组样例启发我们:如果当 x 过于大时,连续花费两个 y 会比只花费一个 x 更优。
0111001
0100001

5 10 1
01100
01100

\(out\)

8
-1
6
0

题解

不合法的情况很简单:不同的数的个数是奇数时就不合法。

然后我们记一个数组 \(C\) , 当 \(a_i = b_i\)\(C_i = 0\),否则 \(C_i = 1\),现在要将 \(C\) 的所有数变为零。

假思路:既然选不相邻的更优,那我就双指针扫(一个从前,一个从后),如果不相邻就加 \(y\) ,相邻就加 \(x\)

\(hack\)\(n = 4, x = 5, y = 3, C = { 1\ 1 \ 1\ 1}\)。我们发现:输出的答案为 \(8\)\(C_1\ C_4\) 同时变为零,\(C_2\ C_3\)同时变为零),但我们可以一眼看穿:答案应该为 \(6\)\(C_1\ C_3\) 同时变为零,\(C_2\ C_4\)同时变为零)。

正解:

如果 \(C\)\(1\) 的个数大于 2,那么我们是可以做到每次选的数是不相邻的:将这些 \(1\) 分成两部分,每次选第一部分的第 \(1、2...\) 个 与第二部分的 \(1、2...\) 个同时变为零,每次选的这两个数一定是隔着 \(\frac{C中一的个数}{2} - 1\) 个数的。答案就是 \(\frac{C中一的个数}{2} \times y\)

否则判断这两个数是否相邻:如果相邻:答案是 \(min(x, y \times 2)\);否则答案就是 \(y\)

Code moo~~
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <set>
using namespace std;
#define int long long
#define re register int
#define pc_ putchar(' ')
#define pc_n putchar('\n')
#define Bessie signed
inline int read() {
    int A = 0, FL = 1;
    char CH = getchar();
    while(CH < '0' || CH > '9') FL = CH == '-' ? -1 : 1, CH = getchar();
    while(CH >= '0' && CH <= '9') A = (A << 3) + (A << 1) + (CH ^ '0'), CH = getchar();
    return A * FL;
}
inline void ot(int x) {
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) ot(x / 10); putchar(x % 10 | '0');
}
const int CTR = 3e3 + 7, INF = 5e5 + 7;
int T;
int n, x, y;
char a[CTR], b[CTR];
int cnt, ans;
int sum[CTR];
int dp[CTR][CTR];
Bessie main() {
    T = read();
    while(T--) {
        n = read(), x = read(), y = read();
        scanf("%s", a + 1);
        scanf("%s", b + 1);
        ans = cnt = 0;
        for(re i = 1; i <= n; ++i) if(a[i] != b[i]) ++cnt;
        if(cnt % 2 != 0) {
            ot(-1),pc_n;
            continue;
        }
        if(cnt == 2) {
            //这原来还写假过:当时没想到不相邻的情况,就直接输出了 min(x, y * 2)
            int fl = 0;
            for(re i = 2; i <= n; ++i) {
                if(a[i] != b[i] && a[i - 1] != b[i - 1]) {
                    ot(min(2 * y, x)),pc_n;
                    fl = 1;
                    break;
                }
            }
            if(fl) continue;
            ot(y),pc_n;
            continue;
        }
        else ot(cnt / 2 * y),pc_n;
    }
    return 0;
}
posted @ 2022-09-23 17:56  Creator_157  阅读(63)  评论(3编辑  收藏  举报