CSU-暑假集训题 Candy Box (easy version)

题目链接:http://codeforces.com/problemset/problem/1183/D

思路:

 这个题真是折磨死我了,我一开始用的方法是先用a数组存储数值出现的次数,然后再用b数组记录出现该次数的次数,下表即次数,值即次数的次数,然后从后往前遍历,如果次数的次数大于1,就加到前面,最后超时。后来我还想了很多办法,都超时,最后我直接舍弃b数值,用排序这个方法。后来我想的方法是先用a数组存储数值出现的次数,然后从大到小排序,然后用flag记录目前要加的次数,然后遍历a数组,如果数值大于flag,就加flag,如果小于flag,就加该数值,其实这个方法是正确的,但还是超时,我就开始怀疑人生了,终于,我发现自己哪里错了,我用的memset这个函数导致的超时,这个函数写起来方便,但不如for循环快,for循环可以局部赋值。

AC代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX=2e5+20;
int a[MAX];
bool cmp(int x,int y){return x>y;}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int num;
        cin>>num;
    //    memset(a,0,sizeof(a));    不能乱用了,时间超限就是因为它 
        for(int i=0;i<=num;i++)a[i]=0;
        int t;
        int ans=0;
        int maxNum=0;
        for(int i=1;i<=num;i++)
        {
            cin>>t;
            a[t]++;
            if(t>maxNum)maxNum=t;
        }
        sort(a,a+maxNum+1,cmp);
        int flag=a[0];
        for(int i=0;i<=maxNum;i++)
        {
            if(a[i]<=0||flag<=0)break;
            if(flag>a[i])flag=a[i];
            ans+=flag;
            flag--;
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xlbfxx/p/11244509.html
今日推荐