POJ 3685 二分套二分
Posted #WoNderlAnd#
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3685 二分套二分相关的知识,希望对你有一定的参考价值。
Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix.
Input
The first line of input is the number of test case.
For each test case there is only one line contains two integers, N(1 ≤ N ≤ 50,000) and M(1 ≤ M ≤ N × N). There is a blank line before each test case.
Output
For each test case output the answer on a single line.
Sample Input
12
1 1
2 1
2 2
2 3
2 4
3 1
3 2
3 8
3 9
5 1
5 25
5 10
Sample Output
3
-99993
3
12
100007
-199987
-99993
100019
200013
-399969
400031
-99939
刚看到题的时候依旧一脸懵逼,不知道从哪开始下手,还是向大佬的题解妥协了
式子是关于i单调递增的(求偏导……都会得……嗯……)然后,找突破口
先二分答案x,然后二分的去找每行<x的个数,根据小于x的个数来调整x的大小。。。——二分套二分……
#include<iostream> #include<stdio.h> #include<cmath> #include<string.h> #include<algorithm> typedef long long ll; using namespace std; ll n, m,t; bool judge(ll a, ll b,ll c) { return (a*a + 100000*a + b*b - 100000*b + a*b)<c; } bool C(ll x) { ll crt = 0; for (int i = 1; i <= n; i++) //i从1开始 { ll le = 0, r = n + 1; while (le<r-1) //找没行多少个小于mid的 { ll mi = (r + le) /2 ; if (judge(mi, i, x)) le = mi; else r = mi; } crt += le; } return crt < m; } int main() { scanf("%lld", &t); while (t--) { scanf("%lld%lld",&n, &m); ll l = -100000*n, h = 3*n*n+100000*n; //不懂为什么换成inf就WA while(h-l>1) { ll mid = (h + l) / 2; if (C(mid)) l = mid; else h = mid; } printf("%lld\n", l); } return 0; }
以上是关于POJ 3685 二分套二分的主要内容,如果未能解决你的问题,请参考以下文章