Codeforces Round #778

本文探讨了三个编程问题:如何找到蛋糕美味值最大组合(A-Maximum Cake Tastiness),通过前缀删除实现字符串简化(B-Prefix Removals),以及验证合法蛋糕切分(C-Alice and the Cake)。通过排序和策略优化,展示了如何在每种情况下找到最优解。
摘要由CSDN通过智能技术生成

A - Maximum Cake Tastiness

题意

给定一个长度为n的蛋糕序列,定义美味值为其中两个相邻的蛋糕美味值的和的最大值可以进行一次子串翻转操作,问最后最大的美味值是多少

题解

我们很容易发现,最大值让两个最大的在一起就行了,翻转子串也很容易得到最大值在一起,所以直接输出两个最大值相加就行了

Code

int n;
int a[N];

void solve(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }
    sort(a + 1, a + 1 + n);
    cout << a[n] + a[n - 1] << endl;
}

B - Prefix Removals

题意

按照规则删除前缀,直到不能删除为止,输出剩下的字符

  • 设x是s的最长前缀的长度,该前缀作为相邻子串出现在s的其他地方(另一种情况也可能与前缀相交)。 如果x = 0,停止。 否则,删除s的前x个字符,重复执行

题解

其实我们发现,如果某一个前缀在后面出现过,那么这个前缀的每一个字符也可以作为一个前缀来删除,所以我们只需要判断每一个字符是否在后面多次出现过就可以了

Code

string s;

void solve(){
    cin >> s;
    map<char, int> m;
    for(auto i : s){
        m[i]++;
    }

    for (int i = 0; i < s.size(); i++){
        if(m[s[i]] > 1)
            m[s[i]]--;
        else{
            cout << s.substr(i, s.size() - i) << endl;
            return;
        }
    }
}

C - Alice and the Cake

题意

给定一个最终切分的蛋糕序列,每一次切割可以将一个大小为w的蛋糕切分为 ⌊ w 2 ⌋ \lfloor\frac{w}{2}\rfloor 2w ⌈ w 2 ⌉ \lceil\frac{w}{2}\rceil 2w两种重量的

问当前给定的蛋糕序列,是否为一个合法的蛋糕切分来的

题解

这个题真的学到到了

很容易我们想到,我们dfs看看是否能用这些数据来进行整合为合法的蛋糕

但是我们发现这并不好做

这个也可以正难则反!

首先我们当然知道,如果这个蛋糕是合法的,那么一定是由 ∑ \sum 重量来分配的

那么我们只需要看看,我们当前的sum能否用现有的这些数凑出来就行了

Code

int T;
int n;
int a[N];
map<ll, int> m;
int ok;

void dfs(ll x){
    if(ok) // 不合法就没有必要再往下了
        return;
    if(m[x]){ // 是否有这个数,有就用一次
        m[x]--;
        n--;
        return;
    }
    else{
        if(x == 1){ // 如果当前切出来的蛋糕出现重量是1的,这个蛋糕就没法往下切了,就说明凑不出来这样的答案
            ok = 1;
            return;
        }
        else{
            ll a = x / 2; // 上下取整
            ll b = (x + 1) / 2;
            dfs(a), dfs(b);
        }
    }
}

void solve(){
    m.clear();
    ok = 0;

    cin >> n;
    ll summ = 0;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
        m[a[i]]++;
        summ += a[i];
    }
    if(n == 1){
        cout << "YES" << endl;
    }
    else{
        dfs(summ);
        if(!ok && !n){ // 是否合法,并且全部都用
            cout << "YES" << endl;
        }
        else
            cout << "NO" << endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值