题目传送门
这道题一看数据就知道一定要离散化。我使用的map离散化(因为好写 (bushi)),将数据对应的次数离散化出来,然后对次数排一个序,对这里面的所有数据循环一遍,求最小的改变次数即可。
但是有一个坑点,就是a数组你开的大,千万不要用memset会超时的,你在最后遍历的时候归零这样就不会超时的。
#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
using namespace std;
typedef long long ll;
map<ll,ll>mp;
ll a[2102102];
ll sum[2102100];
int main(){
ll T;
cin>>T;
ll q=0;
while(T--){
ll n;
scanf("%lld",&n);
ll u=0;
mp.clear();
//if(q)memset(a,0,sizeof a+q);
for(ll i=1;i<=n;i++){
ll b;
scanf("%lld",&b);
if(!mp[b])mp[b]=++u;
a[mp[b]]++;
}
sort(a+1,a+u+1);
for(ll i=1;i<=u;i++)sum[i]=sum[i-1]+a[i];
ll ans=1e9;
for(ll i=1;i<=u;i++){
ans=min(ans,sum[i-1]+(sum[u]-sum[i]-(u-i)*a[i]));
a[i]=0;
}
printf("%lld\n",ans);
q=u+1;
}
return 0;
}
当然正常的离散化代码
int c[210210200];
memcpy(c,a,sizeof a);
sort(c,c+n);
int l=unique(c,c+n)-c;
// l为不重复元素的数量,unique返回的类似于一个指针
//表示除重后容器不重复序列的最后一个元素的下一个元素
int L[21021000];
for (int i=0;i<n;++i)
L[i]=lower_bound(c,c + l,a[i])-c+1;
//a[i]是原数组,c[i]是复制之后的数组