Matrix 锻炼实现能力的好题(POJ 3685)

来源:互联网 发布:淘宝店铺banner全屏 编辑:程序博客网 时间:2024/06/05 00:23

题目来源

Matrix POJ 3685

题意

给一个 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);    }   }

写完发现实现能力还比较差,类似的题求推荐…

原创粉丝点击