I-Interesting Matrix Problem

题意:给你N *M的矩阵 (1<=N , M <=1e8)矩阵内的值是 i乘j 现有q次询问,每次询问输入k 代表 查询这个矩阵内第k小的数是多少。

做法:第一思路二分答案,然后mid去check O(N) 枚举行 i 计算mid/i的个数,发现会超时

写下公式:图片说明

这个公式好眼熟啊,不就是数论的整除分块,果断套了一个分块 时间复杂度:q*sqrt(N)

注意还要判断mid/i 不能大于m

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll n,m,q,k;
int valid(ll mid)
{
    ll ans=0;
    ll l,r;
    for(l=1;l<=mid;l=r+1){
        r=mid/(mid/l);

        ll t=mid/l;
        t=min(t,m);

        ans+=(1ll*r-l+1)*t;
    }
    return ans>=k;
}
void solve()
{
    scanf("%lld%lld%lld",&n,&m,&q);
    if(n>m) swap(n,m);
    while(q--){
        scanf("%lld",&k);


        ll l=1,r=m,ans;
        while(l<=r){
            ll mid=l+r>>1;
            if(valid(mid)) {
                ans=mid,r=mid-1;
                //printf("midmid:%lld\n",mid);
            }
            else l=mid+1;
        }
        printf("%lld\n",ans);
    }
}
int main()
{
    solve();
}