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;
else
r = 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;
else
r = 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掃描,二分b
tmp += bs1(i, mid);
if(tmp>=k)
l = mid+1;
else
r = 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;
}