[JZOJ100043] 【NOIP2017提高A组模拟7.13】第K小数
二分答案$\large mid$, 问题转化成判断是否有$\large k$个数<=mid。
显然不能$\large n^{2}$判断, 不然还不如枚举然后排序。
所以我们先把$\large a$,$\large b$数组从小到大排序。
然后枚举$\large a$的数位置$\large i$, 我们发现当$\large i$递增的时候,满足$\large a[i]*b[j]<=mid$的j的位置一定是单调递减的。
所以我们可以保留$\large j$在上次的位置继续判断。
复杂度$\large O(Nlog(maxnum))$可过。
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; #define reg register #define ll long long inline ll read() { ll res=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } int n, m; ll k, ans, sum; ll a[200005], b[200005]; inline bool check(ll mid) { ll j = m; for (reg ll i = 1 ; i <= n ; i ++) { while (a[i] * b[j] > mid) j --; sum += j; } if (sum >= k) return 1; return 0; } signed main() { n = read(), m = read(); scanf("%lld", &k); for (reg int i = 1 ; i <= n ; i ++) a[i] = read(); for (reg int i = 1 ; i <= m ; i ++) b[i] = read(); sort (a + 1, a + 1 + n); sort (b + 1, b + 1 + m); ll l = 1, r = a[n] * b[m]; while (l <= r) { ll mid = l + r >> 1; sum = 0; if (check(mid)) r = mid - 1, ans = mid; else l = mid + 1; } printf("%lld\n", ans); return 0; }