Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final Round)

 

目录

A. Maximum Cake Tastiness

 B. Prefix Removals

C. Alice and the Cake


A. Maximum Cake Tastiness

  • 题意:

给定一段序列,长度为n:

a_{1},a_{2},a_{3}...,a_{n-1},a_{n}

定义这个序列的值为:

max( \sum_{i}^{n-1}(a_{i}+a_{i+1}))

你可以进行一次操作,选择区间[ l , r ],并翻转区间内的数,使得序列的值最大。

  • 思路: 

找到序列中第二大的数,将它翻转到最大的数旁即可。

即答案就是序列中最大数和次大数的和。

  • 时间复杂度: 

                                                    O(n)

  •  AC代码:

#include<bits/stdc++.h>

typedef long long ll;
typedef unsigned long long ull;

const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;

void solve()
{
    int maxn1 = -1,maxn2 = -1;
    int n;
    std::cin>>n;
    for(int i = 1 ; i <= n ; i++)
    {
        int x;
        std::cin>>x;
        if(x > maxn1)std::swap(maxn1,x);
        if(x > maxn2)std::swap(maxn2,x);
    }
    std::cout<<maxn1+maxn2<<'\n';
}

int main()
{
    std::ios::sync_with_stdio(false);
    int T;
    std::cin>>T;
    while(T--)
    {
        solve();
    }
    return 0;
}

 B. Prefix Removals

  • 题意:

给定一个字符串S,你可以进行如下操作:

选择字符串S的一个前缀,如果这个前缀在

S_{2}S_{3}S_{4}...S_{n-1}S_{n}

中出现,则可以把这个前缀删除

输出进行这个操作若干次以后的最终字符串(即最短字符串)

  • 思路

我们每次都选择长度为1的前缀(即第一个字母)

那么如果后面存在这个字母,显然这个字母是可以是删除的

如果后面不存在这个字母,那么操作结束

易证明这样删除可以得到最短字符串

  • 时间复杂度 

                                                    O(n)                                      

  • AC代码:

#include<bits/stdc++.h>

typedef long long ll;
typedef unsigned long long ull;

const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;

int cnt[30];

void solve()
{
    memset(cnt,0,sizeof cnt);
    std::string s;
    std::cin>>s;
    for(int i = 0 ; i < s.size() ; i++)cnt[s[i] - 'a']++;
    for(int i = 0 ; i < s.size() ; i++)
    {
        if(cnt[s[i]-'a']==1)
        {
            for(int j = i ; j < s.size() ; j++)
                std::cout<<s[j];
            std::cout<<'\n';
            return;
        }
        cnt[s[i]-'a']--;
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    int T;
    std::cin>>T;
    while(T--)
    {
        solve();
    }
    return 0;
}

C. Alice and the Cake

  • 题意:

给定一个初始数w (w >= 2) ,

现将这个数分成两个部分:

w 为 奇数:w/2  , w/2+1(整数除法)

w 为 偶数:   w/2  ,  w/2

可以对拆分完后的数进行继续拆分。

现给出最终拆分后的一个序列:

a_{1},a_{2},a_{3}...a_{n-1},a_{n}

询问原始数 w ,是否存在拆分方案产生给出的序列。

  • 思路: 

显然初始数  w  为序列的和 

我们去模拟拆分过程,把拆分过程中产生的数放入一个优先队列 B

在此之前,把序列 a 也放入一个优先队列 A (multiset也可以)。

我们先把  w  放入优先队列

然后重复一下步骤:

  1. 从B中取出最大数(即top)
  2. 与A中最大数比较,若两数相等,则把两数删除
  3. 若不相等,则把B进行拆分后放入优先队列B

特别的:

  1. 若在比较过程中   B的最大数 < A的最大数,显然为NO

最终:

  1. 若两个优先队列均为空,则为YES,否则为NO
  • 时间复杂度 :

这里稍微分析一下:

  因为优先队列的push操作也是log的,所以时间复杂度要乘上一个log

                                                O(n*(logn)^{2})

AC代码:

#include<bits/stdc++.h>

typedef long long ll;
typedef unsigned long long ull;

const int N = 2e5+10,M = N * 2,INF = 0x3f3f3f3f,P = 9901;

void solve()
{
    std::priority_queue<ll> que_a,que_b;
    int n;
    std::cin>>n;
    ll sum = 0;
    for(int i = 1 ; i <= n ; i++)
    {
        ll x;
        std::cin>>x;
        sum += x;
        que_a.push(x);
    }
    que_b.push(sum);
    while(!que_b.empty())
    {
        ll temp = que_b.top();
        que_b.pop();
        if(temp!=que_a.top()&&temp!=1)
        {
            que_b.push(temp/2);
            que_b.push(temp - temp/2);
        }else if(temp==que_a.top())
        {
            que_a.pop();
        }
        if(que_a.top() > que_b.top())
        {
            std::cout<<"NO\n";
            return;
        }
    }
    std::cout<<"YES\n";
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int T;
    std::cin>>T;
    while(T--)
    {
        solve();
    }
    return 0;
}

 越来越菜了呜呜qwq,用multiset写挂了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值