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

 

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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章