CF1490F题解
题目大意
给出一个数列,将每一个数的出现次数变为
思路
首先肯定要开桶统计每个数的个数,但是注意到数列内的数范围较大,所以要先进行离散化。离散化之后开桶记录每个数的出现次数,则次数又构成了一个新的序列。这样问题就转化为:给出一个序列,对于序列中的每一个数,如果大于等于
我们这样思考:首先假设我们把所有的数都变成
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#define ll long long
using namespace std;
int t,n,maxx,p;
int a[2000005],b[2000005],sum[2000005];
ll summ,ans;
void lisan(){
for(int i=1;i<=n;i++){
b[i]=a[i];
}
sort(b+1,b+1+n);
p=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+1+p,a[i])-b;
}
}
int main()
{
scanf("%d",&t);
while(t--){
summ=0,maxx=0,ans=1000000000000000;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
lisan();
for(int i=1;i<=n;i++){
sum[a[i]]++;
maxx=max(maxx,sum[a[i]]);
// printf("%d ",a[i]);
}
sort(sum+1,sum+1+p);
// for(int i=1;i<=p;i++){
// printf("%d ",sum[i]);
// }
// printf("\n");
// printf("\n");
for(int i=1;i<=p;i++){
ans=min(ans,n-1ll*sum[i]*(p-i+1));
while(sum[i]==sum[i+1]) i++;
}
printf("%d\n",ans);
for(int i=1;i<=p;i++){
sum[i]=0;
}
}
return 0;
}
(由于