POJ 3685 二分套二分
阿新 • • 發佈:2017-08-21
lan ber com 題解 ans a + b number algo 不知道
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 二分套二分