您的位置:首页 > 其它

POJ - 3685 Matrix (二分搜索:查找第k大的值)

2014-04-19 17:44 363 查看
http://poj.org/problem?id=3685

题意:

定义一个N*N矩阵:Aij =  i2 +
100000 × i + j2 -
100000 × j + i × j。

求第M大的值。

N(1 ≤ N ≤
50,000) and M(1 ≤ M ≤ N × N).

——————————————————————————

跟这题有点类似: POJ - 3685 Median(二分搜索,查找第K大的值)

这个矩阵有个规律:每列单调递增。可以根据这个分别对每一列进行二分搜索,求出比x小的个数,得出排在第几位。x的枚举也是通过一个二分搜索得出。

总的时间复杂度为:O(log(MAX_Aij)*N*log(N))。

这里的MAX_Aij懒得算了,就直接用long long的上下限吧……= =。

这题因为二分搜索的上下界出了许多问题,反复调试了很久,感觉while(r - l > 1)这种方法确实不太好。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N = 1e5;
long long N, M;
inline long long getnum(long long i,long long j)
{
return i*i + 100000 * i + j*j - 100000 * j + i * j;
}
bool C(long long x)
{
long long cnt = 0;
for(int j = 1; j <= N; j++)
{
if(x > getnum(N, j))
cnt += N;
else
{
int l = 0, r = N;
while(r - l > 1)
{
int mid = (l+r)/2;
if(getnum(mid, j) >= x)
r = mid;
else
l = mid;
}
//cnt += N - r + 1;
cnt += r - 1;
}
}
//return cnt > N*N-M;
return cnt >= M; //左
}
void solve()
{
//#define DEBUG
#ifdef DEBUG
for(int i = 1; i <= N; i++)
for(int j = 1; j <= N; j++)
printf(j == N ? "%10lld\n": "%10lld ", getnum(i, j));
#endif

if(N == 1)
{
printf("3\n");
return ;
}
long long l = -0x3fffffffffffffff, r = 0x3fffffffffffffff;
while(r - l > 1)
{
long long mid = (l+r)/2;
if(C(mid))
r = mid;
else
l = mid;
}
printf("%lld\n", l);
}

int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &N, &M);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分搜索