1105 第K大的数

基准时间限制:1 秒 空间限制:131072 KB 
数组A和数组B,里面都有n个整数。数组C共有n^2个整数,分别是A[0] * B[0],A[0] * B[1] ......A[1] * B[0],A[1] * B[1]......A[n - 1] * B[n - 1](数组A同数组B的组合)。求数组C中第K大的数。
 
例如:A:1 2 3,B:2 3 4。A与B组合成的C包括2 3 4 4 6 8 6 9 12共9个数。
Input
第1行:2个数N和K,中间用空格分隔。N为数组的长度,K对应第K大的数。(2 <= N <= 50000,1 <= K <= 10^9)
第2 - N + 1行:每行2个数,分别是A[i]和B[i]。(1 <= A[i],B[i] <= 10^9)
Output
输出第K大的数。
Input示例
3 2
1 2
2 3
3 4
Output示例
9
思路:二分,先排序,首先二分答案,答案的范围在ans[0]*bns[0]---ans[n-1]*bns[n-1]之间,然后二分统计这个答案的前面是否有大于等于k个比他大的,符合的话并且二分检查这个答案是否存在。
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<string.h>
 5 #include<queue>
 6 #include<math.h>
 7 #include<set>
 8 #include<vector>
 9 #include<string.h>
10 using namespace std;
11 typedef long long LL;
12 typedef struct node {
13     LL x;
14     LL y;
15 } ss;
16 LL ans[60000];
17 LL bns[60000];
18 bool check(LL n,LL N,LL M) {
19     int i,j;
20     LL cnt = 0;
21     for(i = 0; i < N; i++) {
22         int l = 0;
23         int r =N;
24         int id = -1;
25         while(l<=r) {
26             int mid = (l+r)/2;
27             if(bns[mid]*ans[i]>=n) {
28                 id = mid;
29                 r = mid - 1;
30             } else l= mid + 1;
31         }
32         if(id!=-1) {
33             if(n==12)printf("%d\n",id);
34             cnt += N-id;
35         }
36     }
37     if(cnt>=M)return true;
38     return false ;
39 }
40 bool er(int n,int m,int ask);
41 bool  test(LL mid,LL N,LL M);
42 int main(void) {
43     LL N,M;
44     scanf("%lld %lld",&N,&M);
45     int i,j;
46     for(i = 0; i < N; i++) {
47         scanf("%lld %lld",&ans[i],&bns[i]);
48     }
49     sort(ans,ans+N);
50     sort(bns,bns+N);
51     LL ak = ans[0]*bns[0];
52     LL bk = ans[N-1]*bns[N-1];
53     LL all = -1;//printf("%lld %lld\n",ak,bk);
54     while(ak<=bk) {
55         LL mid = (ak+bk)/2;
56         if(check(mid,N,M)) {
57             if(test(mid,N,M))
58                 all = max(mid,all);
59             ak = mid + 1;
60         } else bk = mid-1;
61     }
62     printf("%lld\n",all);
63     return 0;
64 }
65 bool  test(LL mid,LL N,LL M) {
66     int i,j;
67     LL kk;
68     for(i = 0; i < N; i++) {
69         if(mid%ans[i]==0) {
70             if(er(0,N,mid/ans[i]))
71                 return true;
72         }
73     }
74 }
75 bool er(int n,int m,int ask) {
76     if(n>m)return false;
77     int mid = (n+m)/2;
78     if(bns[mid]==ask) {
79         return true;
80     } else if(bns[mid]>ask) {
81         return er(n,mid-1,ask);
82     } else return er(mid+1,m,ask);
83 }

复杂度N*log(N);


posted @ 2016-08-31 08:39  sCjTyC  阅读(211)  评论(0编辑  收藏  举报