原题
This problem is actually a subproblem of problem G from the same contest.
There are n candies in a candy box. The type of the i-th candy is ai (1≤ai≤n).
You have to prepare a gift using some of these candies with the following restriction: the numbers of candies of each type presented in a gift should be all distinct (i. e. for example, a gift having two candies of type 1 and two candies of type 2 is bad).
It is possible that multiple types of candies are completely absent from the gift. It is also possible that not all candies of some types will be taken to a gift.
Your task is to find out the maximum possible size of the single gift you can prepare using the candies you have.
You have to answer q independent queries.
If you are Python programmer, consider using PyPy instead of Python when you submit your code.
Input
The first line of the input contains one integer q (1≤q≤2⋅105) — the number of queries. Each query is represented by two lines.
The first line of each query contains one integer n (1≤n≤2⋅105) — the number of candies.
The second line of each query contains n integers a1,a2,…,an (1≤ai≤n), where ai is the type of the i-th candy in the box.
It is guaranteed that the sum of n over all queries does not exceed 2⋅105.
Output
For each query print one integer — the maximum possible size of the single gift you can compose using candies you got in this query with the restriction described in the problem statement.
题意
若干个种类的糖果,不同的数字代表不同的糖果,现在要你在糖果中选取,不同种类的糖果的数目是要不同的,问应该怎么选才能使选的糖果的数目最多
题解
首先不难发现,给了众多品牌的糖果数目,那么就要先统计不同类的糖果分别有多少个,新开一个同样大小的数组来将不同种糖果的数目进行保存。
之后,因为要选的糖果的数目不同而且要尽可能的大,那么我们很容易想到贪心的思想,那么我们就对储存糖果不同种类数目的数组进行降序排序。
排序后我们可以发现,显然,第一个数是一定要取的,因为这个数是最大的,那么问题来了,如果后面有数和它一样大,应该怎么处理。这里我们首先很容易想到开一个标记数组,如果发现有重复的值将他标记一下,然后减一即可,直到选取到没有出现过的值。但这样操作显然比较麻烦,那么我们不妨换一种思路:如果后面的这个数与前面的数不相等,那么后面这个数必然可以取到(降序排列),所以我们只需要考虑相等的情况,如果相等,那么能取到的最大的值必然是上一个数减一,这时候注意,不能直接将后面这个数减一处理,因为可能出现多个相同的数相连的情况,但我们要想清楚,最差的情况,后面的数也不会比前面的数大超过1,因为降序排列过,而且前面的数最多减一。所以,一旦出现后面的数比前面的数大,说明前面做过处理,而处理就是将后面的数变成前面的数减一
代码如下
#include <bits/stdc++.h>
using namespace std;
int a[200005];
int b[200005];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);//加速
int n,i,j,k,t,q;
long long s;
cin>>q;
while(q--){
cin>>n;
for(i=0;i<=n;i++)
a[i]=0,b[i]=0;//用多少,初始化多少,直接莽夫memset的话会超时
for(i=0;i<n;i++){
cin>>a[i];
}
for(i=0;i<n;i++)
b[a[i]-1]++;//这里要减一,因为数组是从0开始的
sort(b,b+n,cmp);
s=b[0];
for(i=1;i<n;i++){
if(b[i]>b[i-1]-1){
b[i]=b[i-1]-1;//更新后面的值
}
if(b[i]>0)
s=s+b[i];
}
cout<<s<<endl;
}
return 0;
}
完结!
(太机智了!!)