0
点赞
收藏
分享

微信扫一扫

51nod 第K大区间2(二分)


定义一个区间的值为其众数出现的次数
现给出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;
}

 

举报

相关推荐

0 条评论