51Nod 1686(第K大区间)

来源:互联网 发布:中行外汇行情分析软件 编辑:程序博客网 时间:2024/05/22 17:24
题意:中文题,定义一个区间的值为其众数出现的次数

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

离散化二分答案加尺取判断

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn = 100006;typedef long long ll;int len;int num[maxn];int tmp[maxn];int vis[maxn];int id[maxn];int n;ll k;bool check(int mid){    int flag = 0;    int l=0,r=0; ll ans = 0;    memset(vis,0,sizeof(vis));    while(r<=n){        if(flag ==0)        {            if(r==n) break;            vis[id[r]] ++;            if(vis[id[r]]>=mid) flag = 1;            r++;        }        else        {            while(flag!=0)            {                ans += n-r+1;                vis[id[l]]--;                l++;                if(vis[id[r-1]]<mid) flag = 0;            }        }    }    if(ans>=k) return true;    return false;}int main(){    scanf("%d%I64d",&n,&k);    for(int i=0;i<n;i++) {scanf("%d",&num[i]); tmp[i] = num[i];}    sort(tmp,tmp+n);    len = 0;    for(int i=1;i<n;i++)    {        if(tmp[i]!=tmp[i-1]) tmp[++len] = tmp[i];    }    len++;    for(int i=0;i<n;i++)    {        id[i] = lower_bound(tmp,tmp+len,num[i])-tmp;    }    int l = 1,r = n,mid;    while(l<=r)    {        mid = (l+r)/2;        bool flag = check(mid);        //printf("sgdgghm\n");        if(flag) l = mid+1;        else r=mid-1;    }    printf("%d\n",r);    return 0;}