1. 程式人生 > >ACM_求第k大數(三分)

ACM_求第k大數(三分)

求第k大

Time Limit: 6000/3000ms (Java/Others)

Problem Description:

給定兩個陣列A和B,大小為N,M,每次從兩個陣列各取一個數相乘放入陣列C,最終得到一個N*M的陣列C。求C中第K大的數。

Input:

輸入包含多組測試資料,每組資料首先輸入兩個整數N,M,K,接下來一行有N個整數Ai,再接下來一行有M個整數Bi。(1≤N,M≤10^5,1≤Ai,Bi≤10^5,1≤K≤N*M)

Output:

對於每組資料,輸出答案。

Sample Input:

3 2 2
1 2 3
1 2

2 2 1
1 1
1 1

Sample Output:

4
1
解題思路:
AC程式碼:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn=1e5+5;
 5 int n,m;LL k,l,r,mid,ans,A[maxn],B[maxn];
 6 inline LL read(){///讀入優化
 7     LL x=0,f=1;char ch=getchar();
 8     while(ch<'0'||ch>'9'){if
(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 inline void print(LL x){///輸出優化 13 if(x<0)putchar('-'),x=-x; 14 if(x>9)print(x/10); 15 putchar(x%10+'0'); 16 } 17 bool check(LL mid){ 18 LL cnt=0; 19 for
(int i=0;i<n;++i){ 20 int lt=0,rt=m-1; 21 while(lt<=rt){///二分找b陣列中某個元素與當前A[i]乘積不小於mid的最大下標lt-1 22 int midt=(lt+rt)>>1; 23 if(A[i]*B[midt]>=mid)lt=midt+1;///說明可能還有更小的元素與A[i]相乘之後不小於mid,則往右邊找 24 else rt=midt-1;///否則往左邊找 25 } 26 cnt+=lt;///退出條件是rt=lt-1,而下標是0開始的,所以lt不用減1,累加當前滿足條件的個數 27 } 28 return cnt>=k; 29 } 30 int main(){///時間複雜度為log2(nm)*n*log2(m) 31 while(~scanf("%d%d%lld",&n,&m,&k)){ 32 for(int i=0;i<n;++i)A[i]=read(); 33 for(int i=0;i<m;++i)B[i]=read(); 34 sort(A,A+n,greater<LL>());///降序排 35 sort(B,B+m,greater<LL>()); 36 l=A[n-1]*B[m-1],r=A[0]*B[0]; 37 while(l<=r){///二分找第k大的數(即兩個數的乘積) 38 mid=(l+r)>>1; 39 if(check(mid))l=mid+1;///說明mid可以更大,繼續往右邊找 40 else r=mid-1;///否則往左邊找 41 } 42 print(l-1);puts(""); 43 } 44 return 0; 45 }