cugb1220 两个数组乘积第k大数--二分--2

来源:互联网 发布:win7 32位系统优化 编辑:程序博客网 时间:2024/05/22 05:19

 

http://acm.cugb.edu.cn/JudgeOnline/showproblem?problem_id=1220 

 

 

题意:有两个数组a和b元素个数都有n(10000)个,且均为正整数。。。求a[]*b[]所生成的c[]数组的第k大数。。

 

 

分析:二分求一个值v,这个值是最末尾一个c的元素中>=v的个数>=k。。。然后扫描a数组,二分b数组得到>=v的元素个数。。。

其实二分b数组还可以省略。。。因为a和b数组都是排序了的,那么对a中的元素往后扫,b中元素往后扫就可以得到结果了。。。。

 

二分还是要写死我啊。。。。。

 

 

代码:

一个二分。。100+ms。。难得的rank1啊啊啊。。

#include <stdio.h>#include <algorithm>#include <cmath>#include <iostream>using namespace std;const int N=10010;int n, k, a[N], b[N], flag;int cal(int num){int i, j, k, ans, tmp;if(a[n-1]*b[n-1]<=num)return 0;j = n-1;ans = 0;for(i=0; i<n; i++){for(; j>=0 && a[i]*b[j]>num; j--);ans += n-1-j;}return ans;}int bs() {int i, l, r, mid, ans, tmp;l=1, r=a[n-1]*b[n-1];while(l<=r){flag = 0;mid = (l+r)>>1;tmp = cal(mid);if(tmp>=k)l = mid+1;elser = mid-1;}//r为最后一个满足比r大的个数>=k的值,所以r+1即为所求。。。return r+1;}int main(){int i, j, cas;scanf("%d", &cas);while(cas--){scanf("%d%d", &n, &k);for(i=0; i<n; i++)scanf("%d", &a[i]);for(i=0; i<n; i++)scanf("%d", &b[i]);sort(a, a+n);sort(b, b+n);printf("%d\n", bs());}return 0;}


 

 

两个二分。。300+ms

#include <stdio.h>#include <algorithm>#include <cmath>#include <iostream>using namespace std;const int N=10010;int n, k, a[N], b[N], flag;int bs1(int i, int num) //统计和a[i]相乘>num的总个数{int l, r, mid;l=0, r=n-1;while(l<=r){mid = (l+r)>>1;if(a[i]*b[mid]<=num)l = mid+1;elser = mid-1;}//r为乘积<=num的最后一个位置return n-1-r; //乘积>num的总个数}int bs() {int i, l, r, mid, ans, tmp;l=1, r=a[n-1]*b[n-1];while(l<=r){flag = 0;mid = (l+r)>>1;tmp = 0;for(i=0; i<n; i++) //对a扫描,二分btmp += bs1(i, mid);if(tmp>=k)l = mid+1;elser = mid-1;}//r为最后一个满足比r大的个数>=k的值,所以r+1即为所求。。。return r+1;}int main(){int i, j, cas;scanf("%d", &cas);while(cas--){scanf("%d%d", &n, &k);for(i=0; i<n; i++)scanf("%d", &a[i]);for(i=0; i<n; i++)scanf("%d", &b[i]);sort(a, a+n);sort(b, b+n);printf("%d\n", bs());}return 0;}


 

原创粉丝点击