坚持每日Codeforces三题挑战:Day 8 - 题目详解(2025-06-12,难度:1200,1300,1400)

坚持每日三题第8天:

Problem - B - Codeforces 1200

Problem - C - Codeforces 1300

Problem - B - Codeforces 1400

目录

题目一:

题目大意:

解题思路:

代码(C++):

题目二:

题目大意:

解题思路:

代码(C++):

题目三:

题目大意:

解题思路:

代码(C++):

Python语言写法:

题目一:

题目二:

题目三:


题目一:

Problem - B - Codeforces

题目大意:

现在有一个长度为n的数组a,现在你可以进行以下操作任意次:

选择数组中的一个元素a[i],将a[i]减少任意的数,最少减少到1。

定义MEX(a)为不在数组a中的最小正整数。

现在你需要进行任意次操作,使得数组a的MEX值尽可能大,输出这个最大值。

解题思路:

注意题目中的MEX是最小正整数,不包含0的

所以我们得从1开始找。

我们每次可以把数组中的一个数字减小任意的数量。

我们很明显可以发现,假设数字全是无穷大,

此时MEX的值肯定是数组长度加1,因为可以把这些数字全部变成1到n。

那么我们可以发现这样的求解思路:

从小到大排序数组,设x = 1

从1开始找,每次找到比x大的数字,表示可以把这个数字减少到x。

此时MEX(a) = x + 1。

具体实现看代码

代码(C++):

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }

    //排序
    std::ranges::sort(a);

    //从1开始贪心的找
    int ans = 1;
    for (int& x : a) {
        //每次找到一个比当前大的,表示可以把这个缩小到ans
        //此时MEX为ans + 1
        if (x >= ans) {
            ans++;
        }
    }

    std::cout << ans << "\n";
}

题目二:

Problem - C - Codeforces

题目大意:

现在两个玩家A, B进行游戏,他们刚开始各有一个数组,分别为a, b。

现在玩家A, B刚开始得分都为0,现在从A开始先手进行游戏。

各自的回合,他们可以选择以下两个操作其中一个进行操作:

1.选择自己数组中的一个数字,删除并把这个数字加在自己的分数上。

2.选择对方数组中的一个数字,删除。

现在两个玩家都用最优的操作,并且要使得得分之差尽可能大。

解题思路:

这个题目其实很明显的思路了,不过实现稍微有点麻烦了,我这里用的简单易懂的方法实现的。

最优策略:

如果都有数字,那么比较最大的那个,如果自己的大,就拿自己的,如果对面的大,就删除对面的。

具体实现看代码

代码(C++):

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        std::cin >> b[i];
    }

    std::ranges::sort(a, std::greater<int>());
    std::ranges::sort(b, std::greater<int>());

    i64 s1 = 0, s2 = 0;
    int i = 0, j = 0;
    while (i < n || j < n) {
        //玩家A进行操作
        //两个玩家数组中都有数字的情况
        if (i < n && j < n) {
            if (a[i] > b[j]) {
                s1 += a[i];
                i++;
            } else {
                j++;
            }
        } else if (i >= n && j < n) {
            //玩家A没有数字了,但是玩家B有数字
            j++;
        } else if (i < n && j >= n) {
            //玩家A有数字,但是玩家B没数字
            s1 += a[i];
            i++;
        }

        //玩家B进行操作
        if (i < n && j < n) {
            if (b[j] > a[i]) {
                s2 += b[j];
                j++;
            } else {
                i++;
            }
        } else if (i >= n && j < n) {
            s2 += b[j];
            j++;
        } else if (i < n && j >= n) {
            i++;
        }
    }

    std::cout << s1 - s2 << "\n";
}

题目三:

Problem - B - Codeforces

题目大意:

现在有一个长度为n的数组a,玩家A和B进行游戏,现在A已经把从前往后进行的元素分配:

在这里,给你一个长度为n的字符串S,只包含字符A和B,对于一个下标i。

如果S[i] == ’A‘,表示a[i]为玩家A的数字。

现在玩家B可以进行下述操作一次:

选择数组中的任何一个前缀或者后缀,把对应的数字归属情况进行翻转。

现在玩家的得分为属于自己的数字和。

现在你需要找出,B能获得的最大得分。

解题思路:

代码(C++):

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    std::string s;
    std::cin >> s;

    
    std::vector<i64> prefA(n + 1), prefB(n + 1);
    for (int i = 1; i <= n; i++) {
        prefA[i] = prefA[i - 1];
        prefB[i] = prefB[i - 1];
        if (s[i - 1] == 'A') {
            prefA[i] += a[i - 1];
        } else {
            prefB[i] += a[i - 1];
        }
    }

    i64 ans = prefA[n];
    for (int i = 1; i <= n; i++) {
        ans = std::max(ans, prefA[n] - prefA[i] + prefB[i]);
    }
    for (int i = n; i >= 1; i--) {
        ans = std::max(ans, prefB[n] - prefB[i] + prefA[i]);
    }
    std::cout << ans << "\n";
}

Python语言写法:

题目一:


def solve():
    n = II()
    a = LII()

    a.sort()

    ans = 1
    for x in a:
        if x >= ans:
            ans += 1
        
    print(ans)

题目二:

def solve():
    n = II()
    a = LII()
    b = LII()

    a.sort(reverse=True)
    b.sort(reverse=True)

    s1, s2 = 0, 0
    i, j = 0, 0
    while i < n or j < n:
        if i < n and j < n:
            if a[i] > b[j]:
                s1 += a[i]
                i += 1
            else:
                j += 1
        elif i >= n and j < n:
            j += 1
        elif i < n and j >= n:
            s1 += a[i]
            i += 1
        
        if i < n and j < n:
            if b[j] > a[i]:
                s2 += b[j]
                j += 1
            else:
                i += 1
        elif i >= n and j < n:
            s2 += b[j]
            j += 1
        elif i < n and j >= n:
            i += 1
    
    print(s1 - s2)

题目三:

def solve():
    n = II()
    a = LII()

    s = I()

    pref_a = [0] * (n + 1)
    pref_b = [0] * (n + 1)

    for i in range(1, n + 1):
        pref_a[i] = pref_a[i - 1]
        pref_b[i] = pref_b[i - 1]
        if s[i - 1] == 'A':
            pref_a[i] += a[i - 1]
        else:
            pref_b[i] += a[i - 1]
    
    ans = pref_a[n]

    for i in range(1, n + 1):
        ans = max(ans, pref_a[n] - pref_a[i] + pref_b[i])
    for i in range(1, n + 1):
        ans = max(ans, pref_b[n] - pref_b[i] + pref_a[i])
    
    print(ans)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值