2576: The K-th minimum number 高级二分 矩阵c[i][j]=a[i]*b[j] 求c数组中第k小数

该问题要求在由数组A和B定义的矩阵C中找到第K小的数,C[i][j] = A[i] * B[j]。输入包含矩阵的维度N和M,以及要找的最小数的索引K,输出为矩阵C中的第K小数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2576: The K-th minimum number


ResultTIME LimitMEMORY LimitRun TimesAC TimesJUDGE
5s32768K44138Standard

This problem is finding the K-th minimum number of a Matrix. The matrix is defined as below:

  • 1. The matrix C has N rows and M columns.
  • 2. C[i][j](0<=i<N,0<=j<M) is the number at the i-th row and j-th column of the Matrix.
  • 3. Two arrays A and B is used to represent C. A is an array of N numbers and B is an array of M numbers. C[i][j]=A[i]*B[j] all indices start from 0.

Given the two arrays A and B, your task is to find the Kth minimum number of the Matrix C. K begins with 1.

Input

There will be several cases. Each case includes three lines.

Line 1: Three integers N, M and K.( 1<=N<=10000, 1<=M<=10000, 1<= K <=N*M )

Line 2: N integers of array A. ( -10000 <A[i] < 10000, 0<=i<N)

Line 3: M integers of array B. ( -10000 <B[i] < 10000, 0<=i<M)

The input terminates when N=M=K=0.

Output

For each test case, output the Kth minimum number in Matrix C. A single number takes up a line.

Sample Input

2 2 2
1 2
1 2

2 2 3
1 2
1 2

2 2 1
1 -2
-1 2

2 2 4
1 -2
-1 2

0 0 0

Sample Output

2
2
-4
2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[11000],b[11000];
const int inf=(1<<31)-1;
int n,m,k;
int lessnum(int now)//严格小于
{
    int cnt=0;
    for(int i=0;i<n;i++)//逐行找小于now的数字的个数
    {
        if(a[i]>0)//c[i]行从左往右是递增
        {
            if(a[i]*b[0]>=now) continue;//如果c[i]行最小的仍大于now,则这一行不必再找
            int l=0,r=m;
            while(l<r)//二分查找c[i]行小于now的数字的个数
            {
                int mid=(l+r)>>1;
                if(a[i]*b[mid]<now) l=mid+1;//c[i][j]=a[i]*b[j]
                else r=mid;
            }//查找结束后l表示第一个大于now的数字的位置
            cnt+=l;//因为数组下标是从0开始,所以第一个大于now的数字的位置也是小于now的数字的个数
        }
        else if(a[i]<0)//c[i]行是递减的
        {
            if(a[i]*b[m-1]>=now) continue;//如果c[i]行最小的仍大于now,则这一行不必再找
            int l=0,r=m;
            while(l<r)//二分查找c[i]行大于等于now的数字的个数
            {
                int mid=(l+r)>>1;
                if(a[i]*b[mid]>=now) l=mid+1;
                else r=mid;
            }
            cnt+=m-l;//m-l表示小于now的数字的个数
        }
        else if(now>0) cnt+=m;
    }
    return cnt;
}
void find(int &maxn,int &minc)//找出最大值和最小值,因为数据有可能是负数,所以要考虑四种情况
{
    //找最大值
    if(a[0]*b[0]>maxn) maxn=a[0]*b[0];
    if(a[n-1]*b[0]>maxn) maxn=a[n-1]*b[0];
    if(a[0]*b[m-1]>maxn) maxn=a[0]*b[m-1];
    if(a[n-1]*b[m-1]>maxn) maxn=a[n-1]*b[m-1];
    //找最小值
    if(a[0]*b[0]<minc) minc=a[0]*b[0];
    if(a[n-1]*b[0]<minc) minc=a[n-1]*b[0];
    if(a[0]*b[m-1]<minc) minc=a[0]*b[m-1];
    if(a[n-1]*b[m-1]<minc) minc=a[n-1]*b[m-1];
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&k)==3,n||m||k)
    {
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        for(int i=0;i<m;i++) scanf("%d",&b[i]);
        sort(a,a+n);sort(b,b+m);//从小到大排序
        int maxn=-inf,minc=inf;//初始化最大、小值
        find(maxn,minc);//找最大、小值
        while(minc<maxn)//二分查找第k小数
        {
            int mid=(maxn+minc+1)>>1;//+1 important
            if(lessnum(mid)<k) minc=mid;
            else maxn=mid-1;//-1 important
        }
        printf("%d/n",minc);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值