题意:
给出数组,区间的值为其重数(这个重数是指区间内的重数,不是整个数组的重数),求解第K大小的区间值(重数)
题解:
思路:二分+尺取法
由上知:
重数的范围为 1~~100000
重数值大的区间一定包括重数值小的区间
因此找到有大于等于K个区间值为mid就是答案了
注意:
有可能第K大的值和第K-1个 或者 第 k-2个值相等
例如:
数组 1 2 3 4 4 4 4 4
步骤:
预处理:
先去重(注意 用去重函数得先排序),然后计算原数组中每个数在去重后的数组里面的位置
1···二分重数范围得到mid
2···求解重数为mid的区间有多少个
3···然后就是一般性的二分处理
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 100010
#define LL long long
LL n,k;
LL a[MAXN],b[MAXN],num[MAXN];
int cmp(const void *x,const void *y)
{
return *(LL *)x - *(LL *)y;
}
LL deal(LL number)
{
memset(num,0,sizeof(num));
int left=0,right=0,flag=-1;
LL ans=0;
while(right<n)
{
if(flag==-1&&(++num[a[right++]]>=number))
flag=number;
while(flag!=-1)
{
ans+=(n-right+1);
num[a[left++]]--;
if(num[a[right-1]]<number)
flag=-1;
}
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%lld%lld",&n,&k)!=EOF)
{
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
b[i]=a[i];
}
qsort(b,n,sizeof(b[0]),cmp);
int cnt=unique(b,b+n)-b;
for(int i=0;i<n;i++)
a[i]=lower_bound(b,b+cnt,a[i])-b;
LL ans;
LL left=1,right=n;
while(left<=right)
{
LL mid=(left+right)>>1;
if(deal(mid)>=k)
ans=mid,left=mid+1;
else
right=mid-1;
}
printf("%lld\n",ans);
}
return 0;
}