Codeforces Round #780 (Div. 3)

A. Vasya and Coins

题目链接

题目大意

Vasya 有 a 个 1-burle coin,有 b 个 2-burle coin,问他不能通过不找钱支付的价格的最小值。

思路

 

如果 a 不为 0,从 1 ~ a + b * 2 中的所有价格都可以经过组合进行支付,因此最小不能支付的价格为 a + b * 2 + 1;如果 a 为 0,不论 2-burle coin 有几个,都无法表示 1 这个价格,因此最小不能支付的价格为 1。

 

 代码

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5050;

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int a, b;
        cin >> a >> b;
        if (a == 0)
            cout << 1 << endl;
        else
            cout << b * 2 + a + 1 << endl;
    }
    return 0;
}
复制代码

B. Vlad and Candies

题目链接

题目大意

给定一个序列,第 i 个位置代表第 i 种糖果的数量,每次吃糖果只能吃当前数量最多的糖果,并且每次相邻两次只能吃不同种类的糖果,问是否能够吃完所有糖果。

思路

 

考虑数量最多的糖果,第一次选择这种糖果,第二次就需要选择其它糖果,因此如果数量最多的这种糖果的数量比数量第二多的糖果的数量 + 1 还多,那么第二

次只能吃数量最多的这种糖果,但又不能两次吃相同的糖果,因此一定吃不完所有糖果。反之一定能通过这两种糖果控制其它糖果的数量,从而吃掉所有糖果。

代码

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5050;

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        int s[n + 2];
        int ma1 = 0, ma2 = 0;
        for (int i = 1; i <= n; i++)
        {
            int a;
            cin >> a;
            if (a > ma1)
            {
                ma2 = ma1;
                ma1 = a;
            }
            else if (a == ma1)
                ma2 = a;
            else if (a > ma2)
                ma2 = a;
        }
        if (n == 1)
        {
            if (ma1 == 1)
                cout << "YES\n";
            else
                cout << "NO\n";
        }
        else
        {
            if (ma1 - ma2 <= 1)
                cout << "YES\n";
            else
                cout << "NO\n";
        }
    }
    return 0;
}
复制代码

C. Get an Even String

题目链接

题目大意

定义偶字符串满足 1.长度为偶数;2.对于字符串中每个奇数位置 ia_i = a_{i + 1}。(空字符串也是偶字符串),求给定字符串最少去掉几个字符能得到偶字符串。

思路

 

考虑贪心,找每次第一对出现的相同字符,然后将之间的所有字符抛弃,可以发现这样处理之后,后面剩下的字符中才更有机会找到相同字符。如 aefebfaf,从前往后扫,最先匹配到的是 e,然后抛掉 f 和开头的 a,剩下 bfaf 再匹配到 f,抛掉 a 和开头的 b,因此最终删除的是 4 个字符。再看看先匹配 a 的情况,就需要删除 6 个字符,先匹配 f 的情况也是删除 6 个字符,然后将匹配成功一此计数器加2,总数减去计数器就可以得到答案。
代码

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200;
map<char, int> ma;
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        string s;
        cin >> s;
        int cnt = 0;
        for (int i = 0; i < s.size(); i++)
        {
            if (ma[s[i]] != 0)
            {
                cnt += 2;
                ma.clear();
            }
            else
                ma[s[i]] ++;
        }
        cout << s.size() - cnt << endl;
        ma.clear();
    }

    return 0;
}
复制代码

 D. Maximum Product Strikes Back

题目链接

题目大意

给定一个序列 a(其中-2\leqslant a_i\leqslant 2),定义序列的乘积为序列中每个数相乘的值(空序列的乘积定义为 1),每次可以从最左端或最右端删除元素,问从左、右各删除几个元素能够使得序列乘积最大。

思路

由于 ,空序列值为 1,那么可以把 0 作为分隔符,将每一段的负数个数控制成偶数个(如果是奇数个就比较删除到最左边的一个负数和删除到最右边的一个负数,剩下的序列值的大小,保留较大的一种情况),然后比较每一段的乘积值,由于只有 2 和 -2 对乘积值有贡献,只要计算每段中 abs() = 2 的数个数,最多的即为答案序列,再通过答案序列左右端点可以得到左右删除的元素个数。

代码

复制代码
#include<bits/stdc++.h>
using namespace std;

const int N = 1000010;

int a[N], b[N];

int n;
int ans_x, ans_y, cnt;

void upd(int l, int r) // 更新答案的值
{
    if (l > r) return;
    int t = 0;
    for (int i = l;i <= r;i ++)
    {
        if (abs(a[i]) == 2) t ++;
    }
    if (t > cnt)
    {
        cnt = t;
        ans_x = l - 1;
        ans_y = n - r;
    }
}

int calNeg(int l, int r) // 计算区间内有多少负数
{
    int t = 0;
    for (int i = l;i <= r;i ++) if (a[i] < 0) t ++;
    return t;
}

void cal(int l, int r) // 计算这个区间
{
    int t = calNeg(l, r);
    
    // 如果区间内负数个数为偶数,则这个区间应全部保留
    if (t % 2 == 0) upd(l, r); 
    else
    {
        int id = l;
        while(a[id] > 0) id ++; // 计算第一个负数的下标
        upd(l, id - 1); // 取这个负数的前一段
        upd(id + 1, r); // 和后一段分别计算
        id = r; 
        while(a[id] > 0) id --; // 计算最后一个负数的下标
        upd(l, id - 1); // 取这个负数的前一段
        upd(id + 1, r); // 和后一段分别计算
    }
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    
    int m;
    cin >> m;
    
    while (m --)
    {
        cin >> n;
        for (int i = 1;i <= n;i ++) cin >> a[i];
        
        a[n + 1] = 0; // 特别设置 n+1 的位置为 0
        ans_x = n; // 删除前缀的长度
        ans_y = 0; // 删除后缀的长度
        cnt = 0;
        
        for (int i = 1, j = 1;i <= n + 1;i ++)
        {
            if (a[i] == 0) // 以 0 分隔每一段
            {
                if (i - 1 >= j) cal(j, i - 1); // 只要不是连续的 0,就计算
                j = i + 1; // j为下一段的左端点
            }
        }
        
        cout << ans_x << ' ' << ans_y << endl;
    }
    
    return 0;
}
复制代码

 

posted @   黎_lyh  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示