您的位置:首页 > 其它

poj 3685 Matrix(二分嵌套)

2017-03-02 15:13 288 查看
题目地址:点击打开链接


题意:给你一个n*n矩阵,每一个位置都有一个值,这个值由该点的该点的行列标决定( i^2 + 100000 × i + j^2 - 100000 × j + i × j),问你第m小的元素是多少

思路:

二分答案,然后判断这个答案是在m之前还是之后。那么怎么知道这个二分的值在前在后呢?可以数比他小的数有多少,那怎么数呢?暴力n*n肯定超时,由给出的公式可知j确定时,表达式关于i单调,所以就可以枚举j二分i确定每个j比他小的数由多少个,这样就可以nlogn时间判断,最后复杂度n*logn*logn。

WA:

一开始找到的规律是从右上角开始以对角线形式递增,所以要求第几大,可以通过二分对角线,找到在哪条对角线然后找到行号列号就可以了。。但是不知道为什么wa了...

后来知道了是n到了5*10^4后这个规律就不一定存在了



代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int C = 1e5;
const int maxn = 5e4+5;
ll n, m;

bool judge(ll x)
{
ll num = 0;
for(ll j = 1; j <= n; j++)
{
ll l = 1, r = n, ans = 0;
while(l <= r)
{
ll mid = (l+r)/2;
ll tmp = mid*mid+C*mid+j*j-C*j+j*mid;
if(tmp <= x) l = mid+1, ans = mid;
else r = mid-1;
}
num += ans;
if(num >= m) return 1;
}
return 0;
}

int main(void)
{
int t;
cin >> t;
while(t--)
{
scanf("%lld%lld", &n, &m);
ll ans, l = -C*n, r = n*n+C*n+n*n+n*n;
while(l <= r)
{
ll mid = (l+r)/2;
if(judge(mid)) ans = mid,  r = mid-1;
else l = mid+1;
}
printf("%lld\n", ans);
}
return 0;
}


WA:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int C = 1e5;
const int maxn = 1e5+5;
ll a[maxn], n, m;

void init()
{
for(int i = 1; i <= n; i++)
a[i] = a[i-1]+i;
for(int i = n+1; i <= 2*n-1; i++)
a[i] = a[i-1]+n-(i-n);
}

int main(void)
{
int t;
cin >> t;
while(t--)
{
scanf("%lld%lld", &n, &m);
init();

ll tmp = lower_bound(a+1, a+2*n-1, m)-a, row, col;
if(m <= (1+n)*n/2)
col = n-(a[tmp]-m), row = tmp-(a[tmp]-m);
else
col = n-(tmp-n)-(a[tmp]-m), row = n-(a[tmp]-m);
//        cout << tmp <<endl;
//        cout << row << ' ' << col <<endl;
printf("%lld\n", row*row+C*row+col*col-C*col+row*col);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分 poj