题目来源
题意
给一个 50,000 * 50,000大小的矩阵。
每个位置的值可以用函数f(i,j)计算出来。
要求矩阵中第M大的数
想法
暴力肯定会T
1.找规律发现列不变的情况下,函数值随着行的增加而增加
2.于是就想到了先二分最后答案K
3.再次用二分计算这个答案是矩阵中第几大的
4.第二次二分的方法是 :先枚举每一列,再二分找这一列中小于K的个数
总体说就是二分套二分,但不是很好实现,有些细节需要注意(代码如下)
AC代码
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <cstdio>
#include <math.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#define sc(x) scanf("%d",&x);
#define pr(x) cout << x << endl;
#define bug(x) cout << #x << " = " << x << endl;
#define ppr(x,y) cout << "(" << x << "," << y << ")" << endl;
#define mem(arr,x) memset(arr,x,sizeof arr);
#define clr(arr) mem(arr,0);
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int i,j,t;
LL N,M,K;
int a[maxn];
const LL Get(LL i,LL j){
return i * i + 100000 * i + j * j - 100000 * j + i * j;
}
bool Less(LL val){
LL S = 0;
for(int i = 1 ; i <= N ; i++){
int lb = 0, rb = N + 1;
while(lb + 1 < rb){
int j = (lb + rb) >> 1;
if(Get(j,i) >= val) rb = j;
else lb = j;
}
S += lb;
}
return S < M;
}
int main(){
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
int T; sc(T)
while(T--){
scanf("%lld%lld",&N,&M);
LL lb = -100000 * N, rb = 100000 * N + N * N * 3;
while(lb + 1 < rb){
LL mid = (lb + rb) >> 1;
if(Less(mid)) lb = mid;
else rb = mid;
}
printf("%lld\n",lb);
}
}
写完发现实现能力还比较差,类似的题求推荐…