定义一个区间的值为其众数出现的次数。
现给出n个数,求将所有区间的值排序后,第K大的值为多少。
众数:区间里出现次数最多的数字,例如:1 1 2 2 2,区间[1 1]的众数为1,区间[3 5]的众数为2
收起
输入
第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2) 第二行n个数,0<=每个数<2^31
输出
一个数表示答案。
输入样例
4 2 1 2 3 2
输出样例
2
样例解释:
[l,r]表示区间的值
[1]:3
[2]:1
[3]:2
[4]:4
[1,3]:2
[2,4]:2
第三大是2
通过题意我们知道答案一定在0~n之间,那么我们二分这个区间mid,
通过尺取法找出大于等于mid的区间值的数量,找到与n*(n-1)/2-k+1相等的值即可。
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<iomanip>
#include<math.h>
#include<sstream>
using namespace std;
typedef long long ll;
typedef double ld;
const int INF = 0x3f3f3f3f;
const int maxn=100005;
int n;
ll k;
int a[maxn],b[maxn];
ll mul(ll x)
{
return x*(x-1)/2;
}
ll cala(int x)
{
memset(b,0,sizeof(b));
int i,l=0,la=0;
ll ans=0;
for(i=1; i<=n; i++)
{
b[a[i]]++;
if(b[a[i]]>x)
{
ans+=mul(i-l-1);
ans-=mul(la-l-1);
while(b[a[i]]>x)
{
l++;
b[a[l]]--;
}
la=i;
}
}
ans+=mul(i-l-1);
ans-=mul(la-l-1);
return ans;
}
int main()
{
while(~scanf("%d%lld",&n,&k))
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);//排序
int r=unique(b+1,b+n+1)-(b+1);//去重
for(int i=1; i<=n; i++)
{
a[i]=lower_bound(b+1,b+r+1,a[i])-b;//离散化
}
k=mul(n)-k+1;
int l=0;
r=n;
int mid;
while(l<r)
{
mid=(l+r)/2;
if(cala(mid)>=k)
r=mid;
else
l=mid+1;
}
printf("%d\n",l);
}
return 0;
}