Matrix
| Time Limit: 6000MS |
|
Memory Limit: 65536K |
| Total Submissions: 4150 |
|
Accepted: 1007 |
Description
Given a N × N matrix A, whose element in the i-th row andj-th column
Aij is an number that equals i2 + 100000 ×i +
j2 - 100000 × j + i × j, you are to find theM-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
121 12 12 22 32 43 13 23 83 95 15 255 10
Sample Output
3-99993312100007-199987-99993100019200013-399969400031-99939
Source
POJ Founder Monthly Contest – 2008.08.31, windy7926778
題目意思是給出一個矩陣,這個矩陣中各個元素的值由給定的公式確定。即:i2 + 100000 ×i +
j2 - 100000 × j + i × j。開始打了個10*10的表,以為矩陣元素得大小順序是有規律的,交了後wa了,發現還是不能亂搞。從該式子可以看出,結果隨著i單調遞增,但對j呢?求導後可發現不是單調遞增的,所以找規律就是錯的。求第k大元素嘛,還是考慮二分。二分的關鍵是怎麼去判斷。因為j無單調性可言,那麼就枚舉j,二分找出每列的小於mid的個數cntx,和小於等於mid的個數cnty。總複雜度就是logINF*n*logn,是可以接受的。然後根據相應邏輯判斷即可。這道題,就是二分裡再套二分,還是蠻有意思的。
#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<iostream>#include<map>using namespace std;typedef long long LL;const int maxn = 1000 + 5;const LL INF = 1LL<<40;LL n,m;LL cal(LL i,LL j){ return i*i + 100000 * i + j*j - 100000 * j + i * j;}int can(LL x){ LL cntx = 0,cnty = 0; for(LL i = 1;i <= n;i++){ LL l = 1,r = n; LL tem = -1; while(l <= r){ LL mid = l+(r-l)/2; if(cal(mid,i) < x){ l = mid+1; tem = mid; } else { r = mid-1; } } if(tem != -1){ cntx += tem; } } for(LL i = 1;i <= n;i++){ LL l = 1,r = n; LL tem = -1; while(l <= r){ LL mid = l+(r-l)/2; if(cal(mid,i) <= x){ l = mid+1; tem = mid; } else { r = mid-1; } } if(tem != -1){ cnty += tem; } } if(cnty < m){ return 1; } else if(cntx > m-1){ return -1; } else{ return 0; }}int main(){ int t; scanf("%d",&t); while(t--){ scanf("%I64d%I64d",&n,&m); LL l = -INF,r = INF; LL ans; while(l <= r){ LL mid = l+(r-l)/2; int tag = can(mid); if(tag == 1){ l = mid+1; } else if(tag == -1){ r = mid-1; } else{ ans = mid; break; } } printf("%I64d\n",ans); } return 0;}