zoukankan      html  css  js  c++  java
  • 51NOD 1105 第K大的数

    数组A和数组B,里面都有n个整数。
    数组C共有n^2个整数,分别是:
    A[0] * B[0],A[0] * B[1] ...... A[0] * B[n-1]
    A[1] * B[0],A[1] * B[1] ...... A[1] * B[n-1]
    ......
    A[n - 1] * B[0],A[n - 1] * B[1] ...... A[n - 1] * B[n - 1]
    是数组A同数组B的组合,求数组C中第K大的数。
    例如:
    A:1 2 3,B:2 3 4。
    A与B组合成的C为
    A[0] A[1] A[2]
    B[0] 2 3 4
    B[1] 4 6 8
    B[2] 6 9 12
    共9个数。


    调试日志: 没有弄清二分值在满足条件的情况下是应该尽可能小还是尽可能大


    Solution

    首先对两数组进行排序
    现在解决这一个问题: 给定一个数 (k) 求两两相乘 (n^{2}) 个数中有多少个 (<= k)
    类似 (Two Points) 解决
    因为已经排序, 所以在确定一组解 (a_{i} * b_{j} <= k) 后, 随着 (i) 的递增, 若继续满足条件 (j) 必定递减
    这样便可以在 (O(n)) 的时间内询问一次
    二分 (k) 即可得到答案
    注意这里是第 (K) 小, 需要转换为第 (K)

    然后复习二分
    保险起见, 二分时无论写法默认开区间
    再保险起见, 二分时用变量 (ans) 记录可行答案, 最后返回 (ans)
    这时需要分清二分值在满足条件的情况下是应该尽可能小还是尽可能大
    其实不对你就换一个就OK了, 不过我们不能糟蹋这门学科是吧
    这题需要找的是 序列中的值 , 故二分的值尽可能小(来满足存在于序列中)

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    using namespace std;
    LL RD(){
        LL out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const LL maxn = 100019;
    LL num, K;
    LL a[maxn], b[maxn];
    bool check(LL k){
    	LL cnt = 0;
    	for(LL i = 1, j = num;i <= num;i++){
    		while(a[i] * b[j] > k)j--;
    		cnt += j;
    		}
    	if(cnt < K)return 1;
    	return 0;
    	}
    LL search(LL l, LL r){
    	LL ans;
    	while(l <= r){
    		LL mid = (l + r) >> 1;
    		if(check(mid))l = mid + 1;
    		else ans = mid, r = mid - 1;
    		}
    	return ans;
    	}
    int main(){
    	num = RD(), K = RD(), K = (LL)num * num - K + 1;
    	for(LL i = 1;i <= num;i++)a[i] = RD(), b[i] = RD();
    	sort(a + 1, a + 1 + num), sort(b + 1, b + 1 + num);
    	printf("%lld
    ",search(0, 1e18 + 19));
    	return 0;
    	}
    
  • 相关阅读:
    java输出菱型
    java----内部类
    java中的多重继承
    java算法--三个数字比较大小
    Python基础(2)
    Python基础(1)
    Redis主从同步
    一种高效的进程间的通信方式
    自旋锁和互斥锁的区别
    Linux读写锁的使用
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9745891.html
Copyright © 2011-2022 走看看