1. 程式人生 > >51Nod【1686】——1686 第K大區間(尺取+二分)

51Nod【1686】——1686 第K大區間(尺取+二分)

基準時間限制: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; }