51Nod【1686】——1686 第K大區間(尺取+二分)
阿新 • • 發佈:2019-02-19
基準時間限制:1 秒 空間限制:131072 KB |
---|
定義一個區間的值為其眾數出現的次數。
現給出n個數,求將所有區間的值排序後,第K大的值為多少。
眾數(統計學/數學名詞)_百度百科
Input
第一行兩個數n和k(1<=n<=100000,k<=n*(n-1)/2)
第二行n個數,0<=每個數<2^31
Output
一個數表示答案。
Input示例
4 2
1 2 3 2
Output示例
2
看到一臉懵逼,後來發現看錯題了。。。。。,由於值最後價值為[1,n],所以我們可以通過二分,去檢查二分出來的值是否正確,大於它的是否為k-1個。檢驗的時候可以通過尺取的方式。
#include <bits/stdc++.h>
#define fread(x) freopen(x,"r",stdin)
#define fwrite(x) freopen(x,"w",stdout)
using namespace std;
typedef long long LL;
const int Max = 1e6;
LL arr[Max],a[Max];
int Ls[Max];
int n,k;
int num[Max];
bool ok(int s) {
memset(num,0,sizeof(num));
LL nu = 0; int L = 1 ;
for(int i = 1;i<=n;i++ ){
num[Ls[i]]++;
if(num[Ls[i]] > s) {
while(num[Ls[i]]> s) {
nu+=(n-i+1);
num[Ls[L++]]--;
}
}
if(nu >= k) return false;
}
return nu<=k;
}
int Solve() {
int L = 1 ,R = n,ans = 1;
while(L<=R) {
int mid = (L+R)>>1;
if(ok(mid)) {
ans = mid;
R = mid-1;
}
else L = mid+1;
}
return ans;
}
int main() {
scanf("%d %d",&n,&k);
for(int i =1 ; i<=n;i++) {
scanf("%lld",&arr[i]);
a[i] = arr[i];
}
sort(arr+1,arr+n+1);
arr[0] = 1;
for(int i = 2;i <= n;i++) if(arr[arr[0]] != arr[i]) arr[++arr[0]] = arr[i];
for(int i = 1;i <= n;i++) Ls[i] = lower_bound(arr+1,arr+arr[0]+1,a[i])-arr;
printf("%d\n",Solve());
return 0;
}