首页 > 其他分享 >Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Round)

Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Round)

时间:2023-01-20 20:12:47浏览次数:63  
标签:26 844 int 字母 cnt ++ 字符串 Div Round

《C. Equal Frequencies》

 

 这道题的题意为:一个字符串str上每个字母的数量都一样,为平衡字符串

现在给出一个字符串s,问最少改动多少使s变成平衡字符串,并写出该平衡字符串

  

  这道题我之前一直想要找出一些规律,根本没往暴力方面想,现在想一下  

 

  一个平衡字符串上可能有1~26个字母

  知道一个平衡字符串上有多少字母(这里假设为i个字母),就知道每个字母有多少个

  知道每个字母有多少个(这里假设为x个,x=n/i),我们就可以贪心地

  

  1.如果原来字符串s的字母数(num)>i 

    我们贪心地将字母数最大的i个字母保留,后面 num-i个字母都要变成前i个字母

    同时前i个字母,如果字母数 > x,则要将多出来的部分补到少了的地方

  2.如果原来字符串s的字母数(num)==i

    如果字母数 > x,则要将多出来的部分补到少了的地方

  3.如果原来字符串s的字母数(num)<i

    如果字母数 > x,则要将多出来的部分补到少了的地方

  

  上面的i我们可以从1~26枚举出了

  然后比较得到最少操作数,与对应的平衡字符串上有i个字母时,改动最少

  根据这两个信息我们可以对原字符串进行改动

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
struct node
{
    int n = 0, c;
    bool operator<(const node &t) const
    {
        return n > t.n;
    }
};
void solve()
{
    int n;
    cin >> n;
    vector<node> a(26);
    string str;
    cin >> str;
    for (int i = 0; i < 26; i++)
        a[i].c = i;
    for (int i = 0; i < str.length(); i++)
    {
        int c = str[i] - 'a';
        a[c].n++, a[c].c = c;
    }
    sort(a.begin(), a.end());
    /*  for (int i = 0; i < a.size(); i++)
         cout << a[i].n << " ";
     cout << endl; */
    int ans = 1e9, cnt;
    for (int i = 1; i <= 26; i++)
    {
        int res = 0;
        if (n % i)
            continue;
        int x = n / i;
        // i>=原来字符串中字母个数的情况
        // 将字母个数>x的字母要变成<x的字母;
        for (int j = 0; j < i; j++)
            res += (a[j].n > x ? a[j].n - x : 0);
        // 原来字符串中字母个数的情况>i的情况
        // 只选择字母数排名前i的字母,排名大于i的字母全部变成需要的字母
        for (int j = i; j < 26; j++)
            res += (a[j].n > 0 ? a[j].n : 0);
        if (ans > res)
            ans = res, cnt = i;
    }
    // 开始改变字符串的阶段:
    // 在cnt==原来字符串字母个数时,我们只要改字母数
    // 在cnt>原来字符串字母个数时,我们还要引入新的字母
    // 在cnt<原来字符串字母个数时,我们要将按照字母数排序的前cnt个字母给保留下来
    // 将后面的字母都变成需要的字母
    vector<char> s(n);
    vector<pair<int, int>> pos(26);
    for (int i = 0; i < a.size(); i++)
    {
        int c = a[i].c;
        pos[c] = {a[i].n, i + 1};
        /* cout << char(c + 'a') << " " << a[i].n << " " << i + 1 << endl; */
    }
    int need = n / cnt;
    /*  cout << "need ans cnt: " << need << " " << cnt << endl; */
    for (int i = 0; i < str.length(); i++)
    {
        int c = str[i] - 'a';
        /*  cout << "!: " << char(c + 'a') << " " << pos[c].first << " " << pos[c].second << endl; */
        // 说明需要更换字母
        if (pos[c].first > need || pos[c].second > cnt)
        {
            /* cout << "@: " << i << " "
                 << "entry" << endl; */
            // 在26个字母中找合法的字母
            for (int j = 0; j < 26; j++)
                if (pos[j].first < need && pos[j].second <= cnt)
                {
                    s[i] = j + 'a';
                    /*  cout << "find: " << char(j + 'a') << " " << pos[j].first << " " << pos[j].second << endl; */
                    pos[j].first++;
                    break;
                }
            if (pos[c].first > need)
                pos[c].first--;
        }
        else
        {
            /*  cout << "@: " << i << " "
                  << "entry2" << endl; */
            s[i] = str[i];
            /* cout << s[i] << " " << str[i] << endl; */
        }
    }
    cout << ans << endl;
    for (int i = 0; i < s.size(); i++)
        cout << s[i];
    cout << endl;
}
int main()
{
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

 

    

 

标签:26,844,int,字母,cnt,++,字符串,Div,Round
From: https://www.cnblogs.com/cilinmengye/p/17063139.html

相关文章

  • CF225 Round #139 题解
    比赛链接:https://codeforces.com/contest/225题解:A题意题//bySkyRainWind#include<bits/stdc++.h>#definemprmake_pair#definedebug()cerr<<"Yoshino\n"#de......
  • Codeforces Round #753 (Div. 3)(ABCDE)
    A.LinearKeyboard题意:给26个字母代表你的键盘(没错你的键盘键位是一行)再给你一个字符串,问你打出这个字符串需要消耗多少距离思路:前面几个数据键位没乱当然不用......
  • 「解题报告」ARC141D Non-divisible Set
    很有意思的题,我又没想到咋做。值域为\(2m\),我们要找出一个大小为\(m\)的好集合,我们可以先来分析这个好集合的大小的上界是多少。我们可以猜测一波上界就是\(m\)。可......
  • Codeforces Round #804 (Div. 2)
    题目链接A核心思路也是一个观察性质的过程,但是这个性质比较简单。我们可以发现两个数相等的时候比较好构造。并且我们取另外一个数为1就好了。//Problem:A.TheThir......
  • Codeforces Round #820 (Div. 3) A~F泛做
    一套题学到不少东西A.TwoElevators模拟#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#definecerr(x)std::cerr<<(#x)<<"is"<<(x)<<......
  • [CSS]背景图片很大,根据屏幕缩小适配后,div之间有空隙的问题
    RT。美术给的素材宽度是1080px的。在不缩放的情况下,1080px宽度的屏幕显示div之间正常,没有空隙,但使用transform属性之后,div缩小,div之间有空隙(白线) 百度有人说给这些div......
  • Codeforces Round #807 (Div. 2)
    题目链接A核心思路排序加贪心就好了。//Problem:A.MarkthePhotographer//Contest:Codeforces-CodeforcesRound#807(Div.2)//URL:https://codeforces.......
  • Div高度控制问题
    做网页时尽量是不用设置固定高度的,这样拓展起来更灵活,如果非要设固定高度,就有一些需要注意的地方。IE6和IE7对CSS的解释存在很多差别,今天谈其中一点:height。例子:<div......
  • Codeforces Round #834 (Div. 3) A~E泛做
    A.Yes-Yes?构造一个\(N=50\)的字符串,判断是不是子串即可。#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#definecerr(x)std::cerr<<(#x)<<......
  • background--详解(背景图片根据屏幕的自适应)
    ackground:有以下几种属性:background-colorbackground-positionbackground-sizebackground-repeatbackground-originbackground-clipbackground-attachmentbackgr......