二分-poj-3685-Matrix
题目链接:
http://poj.org/problem?id=3685
题目大意:
有n*n的矩阵,第i行第j列的数为Aij= i2 + 100000 × i + j2 - 100000 × j + i × j,求矩阵中第k小的数。
解题思路:
显然每一列是单调的,二分答案,枚举每一列,再二分行标,求出该列能够满足的个数,从而找到矩阵不超过他的个数。
代码:
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 51000 ll Cal(ll i,ll j) { return i*i+100000*i+j*j-100000*j+i*j; } int main() { int t; ll n,m; scanf("%d",&t); while(t--) { scanf("%I64d%I64d",&n,&m); ll l=-10000000000000LL,r=1000000000000000LL; ll mid,ans; while(l<=r) { mid=(l+r)>>1; ll num=0; for(int col=1;col<=n;col++) //枚举每一列 { ll LL=1,rr=n,mmid; ll tmp=0; while(LL<=rr) { mmid=(LL+rr)>>1; ll res=Cal(mmid,col); if(res<=mid) { tmp=mmid; LL=mmid+1; } else rr=mmid-1; } num+=tmp; //求出该列小于等于mid的个数 } if(num<m) { l=mid+1; } else //注意最小的那个数就是恰好的第k小的那个,因为再比他小的话,肯定没有k个 { ans=mid; r=mid-1; } } printf("%I64d\n",ans); } return 0; }