Codeforces Round #712 (Div. 2)

这篇博客详细解析了Codeforces Round #712 (Div. 2)的比赛题目,包括A. Déjà Vu、B. Flip the Bits和C. Balance the Bits的思路和解决方案。对于A题,提出了两种构造非回文字符串的方法;B题通过预处理和后向遍历来解决位翻转问题;C题通过判断1的个数和贪心策略构造合法括号。D题未提供解答,E题是关于Travelling Salesman Problem的贪心策略解析。
摘要由CSDN通过智能技术生成

题目链接

A. Déjà Vu

思路1

当字符串里面存在a以外的字母,肯定可以构造一个非回文字符串,在将要插入的位置的对称位置看看是不是a,不是a就插入,就可以构造一个非回文字符串.

代码1

#include<bits/stdc++.h>
using namespace std;
void solve()
{
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]!='a')
        {
            puts("YES");
            int was=1;
            for(int j=0;j<s.size();j++)
            {
                if(s[s.size()-j-1]!='a')
                {
                    if(was)
                    {
                        // cout<<i;
                        cout<<"a";
                        was=0;
                    }
                }
                cout<<s[j];
            }
            cout<<endl;
            return;
        }
    }
    puts("NO");
}
int main()
{
    int n;
    cin>>n;
    while(n--)solve();
    return 0;
}

思路2

只需判断首尾插入a就知道能不能构成非回文字符串,.大佬写的,我不知道为什么.

代码2

#include<bits/stdc++.h>
using namespace std;
bool check(string s)
{
    int n=s.size();
    for(int i=0;i<n/2;i++)
        if(s[i]!=s[n-i-1])
            return false;
    return true;
}
void solve()
{
    string s;
    cin>>s;
    if(check(s+'a'));
    else
    {
        cout<<"YES"<<endl;
        cout<<s+'a'<<endl;
        return ;
    }
    if(check('a'+s));
    else
    {
        cout<<"YES"<<endl;
        cout<<'a'+s<<endl;
        return ;
    }
    cout<<"NO"<<endl;
}
int main()
{
    int n;
    cin>>n;
    while(n--)solve();
    return 0;
}

B. Flip the Bits

思路

每次操作需要判断区间内0与1个数是否相等,所以要预处理前缀a[i]表示字符串0~i中0与1的个数相等;然后再从后往前遍历,用个变量v记录操作次数,操作次数为奇数即v=1,则与两个字符串对应字母是否相等的状态取反;为偶数即v=0,则不变;每次俩字符串对应字母不同就改变v(通过v^=1改变);

代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
bool a[N];
void solve()
{
    int n;
    cin>>n;
    string s,t;
    cin>>s>>t;
    memset(a,0,sizeof a);
    int cnt1=0,cnt0=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='1')cnt1++;
        else cnt0++;
        if(cnt1==cnt0)a[i]=true;
    }
    bool v=false;
    for(int i=n-1;i>=0;i--)
    {
        if(s[i]!=t[i])
        {
            if(!v)
            {
                v==0?v=1:v=0;// 等价于v^=1
                if(!a[i])
                {
                    cout<<"NO"<<endl;
                    return ;
                }
            }
        }
        else 
        {
            if(v)
            {
                v==0?v=1:v=0;
                if(!a[i])
                {
                    cout<<"NO"<<endl;
                    return ;
                }
            }
        }
    }
    cout<<"YES"<<endl;
    return ;
}
int main()
{
    int n;
    cin>>n;
    while(n--)solve();
    return 0;
}

C. Balance the Bits

思路

很明显如果01字符串首尾有一个0是不能构造合法括号的;题目说的n是偶数,如果字符串1的个数为奇数,那么0的个数也为奇数,这样的话怎么都构造不出合法括号…所以字符串1的个数必须为偶数.
如果能构造,设有cnt个1,则前cnt/2个1全构造成左括号(贪心),0则是交换构造;

代码

#include<bits/stdc++.h>
using namespace std;
void solve()
{
    int n;
    cin>>n;
    string s;
    string a,b;
    cin>>s;
    int cnt=0;
    for(auto t:s)cnt+=(t=='1');
    if(s[0]!='1'||s[n-1]!='1'||cnt&1)
    {
        cout<<"NO"<<'\n';
        return ;
    }
    bool v=false;
    cout<<"YES"<<'\n';
    for(auto c:s)
    {
        if(c=='1')
        {
            if(cnt>0)a+='(',b+='(';
                else a+=')',b+=')';
                cnt-=2;
        }
        else
        {
            if(v)a+='(',b+=')';
            else a+=')',b+='(';
            v^=1;
        }
    }
    cout<<a<<'\n';
    cout<<b<<'\n';
}
int main()
{
    int n;
    cin>>n;
    while(n--)solve();
    return 0;
}

D.我不会D题,不想补了

E.Travelling Salesman Problem

思路

贪心题, 根据题目描述,显然 cost 最小为 ∑ i = 0 n − 1 a [ i ] . c \sum_{i=0}^{n-1}a[i].c i=0n1a[i].c ;
从 a[i].a 最小的出发,遍历其他所有点, 设a[0].a为a[i].a中最小的点
(若 a[0].a == a[i].a ,则 a[0].c < a[i].c ) ; 则只花费 a[0].c 可到达的点为 a[i].a <= a[0].a + a[0].c 的点; 反之, 花费需要加上 ( a[0].a + a[0].c ) - a[i].a );到达a[i]这个点后,判断a[i]只花费 a[i]可到达的点与a[0]可到达的点的大小 ( 即 a[i].a + a[i].c > or <= a[0].a + a[0].c ) ;然后更新可到达的点的大小;重复上面的步骤;

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int M=1e5+10;
struct node{
    int a,c;
}ai[M];
bool cmp(const node &x,const node &b)
{
    if(x.a==b.a)return x.c<b.c;
    return x.a<b.a;
}
signed main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;
    cin>>n;
    for(int i=0;i<n;i++)cin>>ai[i].a>>ai[i].c;
    sort(ai,ai+n,cmp);
    int ans=ai[0].c;
    int v=ai[0].a+ai[0].c;
    for(int i=1;i<n;i++)
    {
        ans+=ai[i].c;
        if(ai[i].a>v)
        {
            ans+=ai[i].a-v;
        }
        v=max(v,ai[i].a+ai[i].c);
    }
    cout<<ans<<'\n';
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值