kuangbin专题23 二分 尺取 单调栈队列
|
Matrix
|
题意:给你一个n * n的矩阵,矩阵一点的值是i^2 + 100000 × i + j^2 - 100000 × j + i × j,问在整个矩阵中第m大的值是多少。
//想分解公式但是什么都没看出来,这个公式是用于判断单调性的 //主函数里面二分答案,check二分查找有多少个小于当前M的数
//显然x越大结果越大,相同y情况下对于x是递增的(根据此二分)
#include<iostream> #include<algorithm> #include<string> #include<map> #include<cmath> #include<string.h> #include<stdio.h> #include<queue> #include<stack> #include<set> #define endl "\n" typedef long long ll; using namespace std; //想分解公式但是什么都没看出来,这个公式是用于判断单调性的 //主函数里面二分答案,check二分查找有多少个小于当前M的数 ll n,m; ll calc(ll x,ll y){ //显然x越大结果越大,相同y情况下对于x是递增的(根据此二分) return x*x+100000*x+y*y-100000*y+x*y; } bool check(ll x){ ll cnt=0; for(ll j=1;j<=n;j++){ ll L=0,R=n+1; while(L+1<R){ ll M=(L+R)>>1; if(x>calc(M,j))L=M; else R=M; } cnt+=L; } return cnt<m; } int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int T=1;cin>>T; while(T--){ cin>>n>>m; ll L=-1e12,R=1e12; while(L+1<R){ ll M=(L+R)>>1; if(check(M))L=M; else R=M; } cout<<L<<endl; } return 0; }