JZOJ 100043. 【NOIP2017提高A组模拟7.13】第K小数
生活随笔
收集整理的這篇文章主要介紹了
JZOJ 100043. 【NOIP2017提高A组模拟7.13】第K小数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
有兩個正整數數列,元素個數分別為N和M。從兩個數列中分別任取一個數相乘,這樣一共可以得到N*M個數,詢問這N*M個數中第K小數是多少。
Input
輸入文件包含三行。
第一行為三個正整數N,M和K。
第二行為N個正整數,表示第一個數列。
第三行為M個正整數,表述第二個數列。
Output
輸出文件包含一行,一個正整數表示第K小數。
Sample Input
Sample1:
2 3 4
1 2
2 1 3
Sample2:
5 5 18
7 2 3 5 8
3 1 3 2 5
Sample Output
Sample1:
3
Sample2:
16
Data Constraint
Solution
看到 “第 K 小”,我們首先把讀入的 a,b 兩個數組從小到大排一遍序,方便處理。
考慮二分答案,將求值問題轉化成判定性問題。
設二分到一個值 mid ,那么前 K 小的數都滿足 a[i]?b[j]<=mid ;
于是我們枚舉 i ,算出 j ,得到數的個數,看滿不滿足 K 的條件。
接著我們如何算出 j 呢?二分?不,這樣時間復雜度就是 O(N?log(MaxNum)?logN) 。
這復雜度可能遇到常數問題,但我們觀察到枚舉的 a[i] 是 遞增 的(排過序了)。
所以得到的 j 是 單調遞減 的(總乘積不變),利用單調性解決即可。
時間復雜度為 O(N?log(MaxNum)) ,輕松通過。
Code
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; const int N=200001; int n,m; LL k; LL a[N],b[N]; inline int read() {int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w; } int main() {n=read(),m=read(),scanf("%lld",&k);for(int i=1;i<=n;i++) a[i]=read();for(int i=1;i<=m;i++) b[i]=read();sort(a+1,a+1+n);sort(b+1,b+1+m);LL l=1,r=a[n]*b[m];while(l<r){LL mid=(l+r)>>1,sum=0;for(int i=1,x=m;i<=n;i++,sum+=x)while(a[i]*b[x]>mid) x--;if(sum>=k) r=mid; else l=mid+1;}printf("%lld",l);return 0; }總結
以上是生活随笔為你收集整理的JZOJ 100043. 【NOIP2017提高A组模拟7.13】第K小数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 100041. 【NOIP20
- 下一篇: JZOJ 100045. 【NOIP20