题目链接
题意:
给了一串数字,定义数字的Mode值是出现次数最多的数字,现在可以恰好删除m个数字,Mode值只允许为一个值,求出最大的Mode值为多少,否则输出-1。
思路:
要让某一个值是Mode,需要把比它出现次数多的和与它次数相同的至少降低到比它出现的次数少1。
基于这个想法,可以先处理出每个值出现的次数并将它按照次数的降序来排序。然后O(N)的跑一次,将每个值作为Mode,只要满足m次删除能够将比它次数times大于或者等于的降低到times-1就行了。m多余的删除次数随便删就行了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=1e5+5;
map<int,int>mp;
struct node
{
int v;
int times;
}q[maxn];
int r[maxn];
int sum[maxn];
bool cmp(node a,node b)
{
if(a.times!=b.times)
return a.times>b.times;
return a.v>b.v;
}
int main()
{
int t,x,n,m;
scanf("%d",&t);
while(t--)
{
memset(q,0,sizeof(q));
memset(sum,0,sizeof(sum));
scanf("%d%d",&n,&m);
mp.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
mp[x]++;
}
map<int,int>::iterator it;
int cnt=1;
for(it=mp.begin();it!=mp.end();it++)
{
q[cnt].v=it->first;
q[cnt].times=it->second;
cnt++;
}
sort(q+1,q+1+cnt,cmp);//按照times降序排序
for(int i=cnt-1;i>=1;i--)//求出和它的times值相同的最右能达到的位置
{
if(i==cnt-1)
r[i]=i;
else
{
if(q[i].times!=q[i+1].times)
{
r[i]=i;
}
else
{
r[i]=r[i+1];
}
}
}
for(int i=1;i<cnt;i++)
{
sum[i]=sum[i-1]+q[i].times;
}
int ans=-1;
for(int i=1;i<cnt;i++)
{
int zong=sum[i-1]-(q[i].times-1)*(i-1)+r[i]-i;
if(m>=zong)
{
ans=max(ans,q[i].v);
}
}
printf("%d\n",ans);
}
return 0;
}