zoukankan      html  css  js  c++  java
  • poj 3685

     /*
        给定n,有n*n个数,有aij=i * i + m * i + j * j - m * j + i * j
        n <= 50000
        m <= 100000
        求所有aij中第m大的数
    
        还是二分答案,先根据生成的式子,求出最大的和最小的数字,然后二分答案,验证
        我们发现,对于同列的数字,按照行数的增加,数字大小是递增的
        根据这个性质,就很容易验证是否存在>=n*n-m+1个数字>=val了
    
        看了题一下子就有想法了,结果却wa了一天...原因在于自作聪明地进行数学推论然后非要从同行中进行二分...最后才发现不满足递减性质...不过最后ac的时候还是很爽快的 
    */
    #include <cstdio>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #define range(i,a,b) for (long long i=a;i<=b;i++)
    
    using namespace std;
    
    typedef long long ll;
    
    const ll m = 1e5;
    
    ll n;
    ll M;
    
    inline ll Int(ll i,ll j)
    {
        return i * i + m * i + j * j - m * j + i * j;
    }
    
    //找到最小的i,满足>=val
    ll findK(ll j,ll val)
    {
        ll l(1),r(n);
        while(l+1<r)
        {
            int mid = (l+r)>>1;
            if (Int(mid,j) >= val)
                r = mid;
            else
                l = mid;
        }
        //返回>=val的数字的个数
        if (Int(l,j) >= val)
            return n-l+1;
        if (Int(r,j) >= val)
            return n-r+1;
        return 0;
    }
    
    bool test(ll val)
    {
        ll ans(0);
        //返回每一行的>=val的数量
        range(c,1,n)
        {
            ans += findK(c,val);
        }
    
        return ans >= (ll)n*n - M+1;
        //必须要有>=n*n-M+1的数量>=ans,ans才有可能是答案
    }
    
    int main()
    {
        int t;
        cin>>t;
    
        range(c,1,t)
        {
            cin>>n>>M;
            ll l(-n*m),r(n*n*3 + n*m);
            while(l+1<r)
            {
                ll mid = (l+r)/2;
                if (mid == 5101786214)
                {
                    cout<<"";
                }
                if (test(mid))
                {
                    l = mid;
                }
                else
                {
                    r = mid;
                }
            }
            if (test(r))
            {
                cout<<r<<endl;
            }
            if (test(l))
            {
                cout<<l<<endl;
            }
    
        }
        return 0;
    }
  • 相关阅读:
    第六章 函数与宏定义实验报告
    第三次实验报告
    第五章 循环结构课后反思
    第二次实验报告
    第一次实验报告
    安装OpenCV时提示缺少boostdesc_bgm.i文件的问题解决方案
    2020软件工程最后一次作业
    2020软件工程第四次作业
    2020软件工程第三次作业
    2020软件工程第二次作业
  • 原文地址:https://www.cnblogs.com/dandi/p/4077344.html
Copyright © 2011-2022 走看看