51nod 1686 第K大区间【离散化+二分】

来源:互联网 发布:酒店管理系统数据库 编辑:程序博客网 时间:2024/05/06 08:08

题目链接:

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1686

题意:

定义一个区间的值为其众数出现的次数。
现给出n个数,求将所有区间的值排序后,第K大的值为多少。

分析:

二分答案,对于每个值判断大于等于该值的区间个数是否大于等于K
判断某个值mid时枚举右端点,找到使得以该右端点为众数的最大的左端点。那么该区间就是满足题意的一个最小的区间之一,再加上前面的区间外的元素,就可以得到右端点为该点的满足条件的区间数。这样保证了任何被加进去的区间中的众数至少为mid。

代码:

#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1e5 + 5;int a[maxn], b[maxn];int cnt[maxn];int n;long long k;bool judge(int mid){    long long ans = 0;    int  l = 1;    bool flg = false;    memset(cnt, 0,  sizeof(cnt));    for(int i = 1; i <= n; i++){        cnt[a[i]]++;        if(cnt[a[i]] >= mid){            flg = true;            if(cnt[a[i]] > mid){                l++;                cnt[a[i]]--;            }            while(a[l] != a[i]){                l++;                cnt[a[l]]--;            }        }        if(flg)  ans += l;    }    return ans >= k;}int main (void){    cin>>n>>k;    int maxx = 0;    for(int i = 1 ;i <= n; i++){            cin>>a[i];            b[i] = a[i];    }    sort(b + 1, b +1 + n);    int t = unique(b + 1, b + n + 1) - (b + 1);    for(int i = 1; i <= n; i++){        a[i] = lower_bound(b + 1, b + t + 1, a[i]) - (b + 1);    }    int l = 1, r = n + 1;    while(l + 1 < r){        int mid = l + r>>1;        if(judge(mid)) l = mid;        else r =mid;    }    cout<<l<<endl;    return 0;}
0 0
原创粉丝点击