51nod 1686 二分+离散化
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1686
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
收藏
关注
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 }