题解:Atcoder - ABCF - Best Concatenation(洛谷T_abc268_f[ABC268F] Best Concatenation)

文章介绍了如何解决Atcoder和洛谷上的一个算法问题,BestConcatenation。该问题涉及贪心策略和字符串处理,通过比较字符串中X的数量和数字之和来优化字符串排列,从而计算最大得分。解决方案包括对字符串进行排序,并使用特定条件判断是否交换字符串位置以改进总分。
摘要由CSDN通过智能技术生成

题解:Atcoder - ABCF - Best Concatenation洛谷T_abc268_f[ABC268F] Best Concatenation

·题目

Atcoder链接:F - Best Concatenation

洛谷链接:[ABC268F] Best Concatenation

·难度

算法难度:普及

思维难度:提高

调码难度:普及

综合评价:偏难

·算法

贪心+sort排序

·思路

对于每一个字符串s,有两个属性:‘X’的个数、所有数字的和。假设s[p`[1]]s[p`[2]]s[p`[3]]...s[p`[n]]为最优排列,我们任意找到两个连续字符串s[i],s[i+1]进行交换,在i-1及之前的字符串分数总和肯定不会比变化(s[i]与s[i+1]的变化不会影响到它们),i+2及之后的字符串的分数综合也不变(它们之前的x的个数【记作y】不变,一直是y[1]+y[2]+...+y[i]+y[i+1],里面的数字也不变),改变的只有s[i]与s[i+1]的分数。如果交换后比交换前整个字符串更优,则交换后比交换前s[i]s[i+1]更优。因此若要在原排列的基础上交换两个字符串s[i]与s[j](i<j)的排列顺序,必须要满足<s[i]的X个数>*<s[j]的数字之和>小于<s[j]的X个数>*<s[i]的数字之和>(这里消去了一些交换前与交换后不变的项,比如说s[i]与s[j]内部的分数总和)。

按照这种方式找出排列方式之后,依次连接统计分数即可(开long long)。

·代码

Atcoder链接:Submission #42998483 - AtCoder Beginner Contest 268 - F

洛谷链接:记录详情

#include<bits/stdc++.h>
#define N 220000
using namespace std;
string str[N]={};
long long ans=0;
int p[N]={},sn[N]={},sx[N]={},n=0,sum=0;
bool cmp(int x,int y);
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        p[i]=i;
        cin>>str[i];
        for(auto j:str[i]){
            if(j=='X'){
                sx[i]++;
            }else{
                sn[i]+=j-'0';
            }
        }
        //统计‘x’总个数(sx)与数字总和(sn)
    }
    sort(p+1,p+1+n,cmp);
    //按照以上规律排序,冒泡太慢采用快排
    for(int i=1;i<=n;i++){
        for(auto j:str[p[i]]){
            if(j=='X'){
                sum++;
            }else{
                ans+=sum*(j-'0');
            }
        }
    }
    //一次遍历最有排列后每个字符串并计算分数
    printf("%lld\n",ans);
    return 0;
}
bool cmp(int x,int y){
    if(sn[y]*1LL*sx[x]>sn[x]*1LL*sx[y]){
        //如果交换前的分数比交换后的分数高则不能交换,注意如果不加*1LL会炸int
        return true;
    }
    //否则交换
    return false;
}

·注意

①对于答案统计和排序cmp中分数计算,都要开longlong。

②‘X’其实是大写。

③不可以写冒泡排序,虽然看起来更合理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值