基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
收藏
关注
定义一个区间的值为其众数出现的次数。
现给出n个数,求将所有区间的值排序后,第K大的值为多少。
Input
第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2)第二行n个数,0<=每个数<2^31
Output
一个数表示答案。
Input示例
4 21 2 3 2
Output示例
2
二分答案t,统计众数出现次数大于等于t的区间有多少个。
枚举右端点R,计算左端点L最大为多少,使得区间[L,R]的值大于等于t,对于每个R他对答案贡献为L。
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long ll;
vector<int> v[maxn];
int num1[maxn], num2[maxn], p[maxn];
ll n, k, len;
bool judge(int m){
ll ans = 0;
int kk = -1;
for(int i = 0; i < n; i++){
int d = lower_bound(num2, num2+len, num1[i]) - num2;
p[d]++;
if(p[d] >= m){
kk = max(kk, v[d][p[d]-m]);
}
if(kk != -1){
ans += kk + 1;
}
if(ans >= k)
return true;
}
return false;
}
int main(){
// freopen("in.txt", "r", stdin);
scanf("%I64d%I64d", &n, &k);
for(int i = 0; i < n; i++){
scanf("%d", num1+i);
num2[i] = num1[i];
}
sort(num2, num2+n);
len = unique(num2, num2+n) - num2;
for(int i = 0; i < n; i++){
int e = lower_bound(num2, num2+len, num1[i]) - num2;
v[e].push_back(i);
}
int l = 1, r = n+1;
while(l < r){
memset(p, 0, sizeof(p));
int mid = (l + r) >> 1;
if(judge(mid) == false)
r = mid;
else
l = mid + 1;
}
printf("%d\n", l - 1);
return 0;
}