51nod 1686 二分+离散化

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

1686 第K大区间

基准时间限制: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 2
1 2 3 2
Output示例
2
一开始以为是第k大的值,后来发现是第K大区间的值,重复的也要计算在内。
二分k表示区间值大于等于k的区间的个数,个数小于K区间值小于等于k的都在答案的上面,否则说明答案包含在k之上。
在找区间个数的函数内可以使用尺取法,由于要统计出现次数所以进行离散化一下,用mapT了一个点,最后用结构体按照下标映射A掉。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 struct node
 5 {
 6     int v,id;
 7 }P[100005];
 8 bool cmpid(node A,node B){return A.id<B.id;}
 9 bool cmpv(node A,node B){return A.v<B.v;}
10 int M[100005];
11 LL book[100005];
12 LL solve(int k,int n)
13 {
14     LL s=0,l=1,maxn=1;
15     memset(book,0,sizeof(book));
16     for(int i=1;i<=n;++i)
17     {
18      LL x=++book[M[i]];
19      if(x>maxn)maxn=x;
20      if(maxn==k){
21         while(maxn==k&&l<=i){
22             s+=n-i+1;
23             LL y=book[M[l]]--;
24             if(maxn==y) maxn--;
25             l++;
26         }
27      }
28     }
29     return s;
30 }
31 int main()
32 {
33     int n,i,j,p=0;
34     LL k;
35     cin>>n>>k;
36     for(i=1;i<=n;++i) scanf("%d",&P[i].v),P[i].id=i;
37     sort(P+1,P+1+n,cmpv);
38     for(i=1;i<=n;++i)
39     {
40        if(P[i].v==P[i-1].v) M[P[i].id]=M[P[i-1].id];
41        else M[P[i].id]=++p;
42     }
43     sort(P+1,P+1+n,cmpid);
44     int l=1,r=n;
45     while(l<r){
46         int mid=r-(r-l)/2;
47         //cout<<l<<' '<<r<<' '<<mid<<endl;
48         if(solve(mid,n)<k) r=mid-1;
49         else l=mid;
50     }
51     cout<<l<<endl;
52     return 0;
53 }

 

posted @ 2017-08-29 15:49  *zzq  阅读(193)  评论(0编辑  收藏  举报