首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

2分-poj-3685-Matrix

2013-09-29 
二分-poj-3685-Matrix题目链接:http://poj.org/problem?id3685题目大意:有n*n的矩阵,第i行第j列的数为Aij

二分-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 51000ll 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;}




热点排行