$CF546B Soldier and Badges$

[$ CF546B \ Soldier \ and \ Badges\(](https://www.luogu.org/problem/CF546B) 这道题看到许多大佬使用了```sort```,十分高端,本蒟蒻表示\)%%%\(,但是,我们还可以用一种更快也更容易想到的方法解决这道题。所以,本题解就来介绍这种方法来\)A$了这道题。


\[First:\text{数据存储} \]

本题解使用的这种方法的思想可以被近似的看成桶排序,我们建一个数组为原数组,就是要输入的数组,不妨设为\(a[]\),因为题目中的数据要求是\((1 \leq n \leq 3000)\),所以,\(a[]\)数组大小应该是\(a[3005]\),再设一个类似于的数组,即\(flag[]\)\(flag\)数组的作用是统计某个数出现的次数,题目又规定\((1 \leq a_i \leq n)\),所以,注意了, 注意了, 注意了, 这里\(flag\)数组的大小应设为\(n\)\(2\)倍,为什么呢?应为\(flag\)数组的作用是统计某个数出现的次数,而题目又规定每进行一次操作可以将一个数\(+1\),而我们考虑最差的情况,就是\(n\)为最大,即\(3000\),而每一个数\(a_i\)又都是跟\(n\)一样的,此时,数\(a_i\)最大为\(6000\),所以,\(flag\)数组应成跟\(n \times 2\)这么大,即开成\(flag[6001]\)
至于代码实现十分简单,如下:

int n,flag[6001],a[6001];   //a[]是要输入的数组,flag[]为桶
cin>>n;
for(int i=1;i<=n;i++)
{
    cin>>a[i];  //输入
    flag[a[i]]++;  //桶中每个元素出现的次数++
}

好了,就此,我们把数据存储的问题解决了,接下来,我们再来实际解决问题。\((QAQ)\)


\[Second:\text{正式解决问题} \]

其实本题通过简单的枚举就可以做出来了,枚举的范围应该为\(n \times 2\),至于原因前文已经阐述过了,原因和前面一样,为了考虑最差的情况吗。其他解释都在\(code\)里,自己慢慢查看\(qwq\),(其中\(sum\)的含义是要进行几次操作)

    for(int i=1;i<=n*2;i++)  //开始枚举
    {
        if(flag[i]>1)  //又两个及以上元素
        {
            flag[i+1]+=(flag[i]-1);//多了几个数就下一个桶就加几
            sum+=(flag[i]-1);  //多了几个数就要进行几次操作
            flag[i]=1;  //清除多余的次数
        }
    }

好了,本题解就告一段落,希望读者明白了该算法的含义并会灵活运用,下面给出完整代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,flag[6001],a[6001],sum=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        flag[a[i]]++;
    }
    for(int i=1;i<=n*2;i++)
    {
        if(flag[i]>1)
        {
            flag[i+1]+=(flag[i]-1);
            sum+=(flag[i]-1);
            flag[i]=1;
        }
    }
    cout<<sum;
    return 0;
}

\[bye \ bye(QAQ) \]

posted @ 2019-08-12 13:52  Luke·Skywalker  阅读(99)  评论(0)    收藏  举报