zoukankan      html  css  js  c++  java
  • P4357-[CQOI2016]K远点对【K-Dtree】

    正题

    题目链接:https://www.luogu.com.cn/problem/P4357


    题目大意

    平面上给出(n)个点,求第(k)远的点对距离。


    解题思路

    ( ext{K-Dtree})的模板题,但是这里只有二维,大概是每次根据一个维度把(n)个点分成两半像线段树一样丢到下面继续分治的思想来构建一棵树。

    那么这样分割出来的每个节点的点分割了自己的矩形范围成了两个子节点的矩形范围。

    这题的话我们就先构造出( ext{K-Dtree})然后记录一下每个节点的矩形范围。

    之后开一个小根堆,里面先丢(2k)(0)(因为会算重),然后每次找到的一个点对距离如果比堆顶大就要换一个新的进堆就好了。

    这样就保证了堆里存的是前(2k)大的点对了,之后每次用矩形范围判断一下新的答案是否在某个子节点的矩形里面。

    理论上为了保证复杂度是需要替罪羊重构的,但是这题数据比较小就好很多。

    因为(k)比较小所以能保证复杂度


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<queue>
    #define ll long long
    #define pw(x) ((x)*(x))
    using namespace std;
    const ll N=4e5+10,inf=1e18;
    struct point{
        ll x[2];
    }w[N],p[N];
    ll n,k,cnt,opt,mx[N][2],mi[N][2],ls[N],rs[N];
    priority_queue<ll> q;
    bool cmp(point x,point y)
    {return x.x[opt]<y.x[opt];}
    ll gdis(point x,point y)
    {return pw(x.x[0]-y.x[0])+pw(x.x[1]-y.x[1]);}
    ll limd(point x,ll y)
    {return max(pw(x.x[0]-mx[y][0]),pw(x.x[0]-mi[y][0]))+max(pw(x.x[1]-mx[y][1]),pw(x.x[1]-mi[y][1]));}
    void PushUp(ll x){
        ll l=ls[x],r=rs[x];
        mx[x][0]=mi[x][0]=w[x].x[0];
        mx[x][1]=mi[x][1]=w[x].x[1];
        if(l){
            for(ll i=0;i<2;i++)mx[x][i]=max(mx[x][i],mx[l][i]);
            for(ll i=0;i<2;i++)mi[x][i]=min(mi[x][i],mi[l][i]);
        }
        if(r){
            for(ll i=0;i<2;i++)mx[x][i]=max(mx[x][i],mx[r][i]);
            for(ll i=0;i<2;i++)mi[x][i]=min(mi[x][i],mi[r][i]);
        }
        return;
    }
    void Build(ll &x,ll l,ll r,ll z){
        if(l>r)return;x=++cnt;
        ll mid=(l+r)>>1;opt=z;
        nth_element(p+l,p+mid,p+r+1,cmp);
        w[x]=p[mid];
        Build(ls[x],l,mid-1,z^1);
        Build(rs[x],mid+1,r,z^1);
        PushUp(x);return;
    }
    void Query(ll x,point v){
        if(!x)return;
        ll dl=-inf,dr=-inf;
        if(ls[x])dl=limd(v,ls[x]);
        if(rs[x])dr=limd(v,rs[x]);
        ll dis=gdis(w[x],v);
        if(dis>-q.top())q.pop(),q.push(-dis);
        if(dl>dr){
            if(dl>-q.top())Query(ls[x],v);
            if(dr>-q.top())Query(rs[x],v);
        }
        else{
            if(dr>-q.top())Query(rs[x],v);
            if(dl>-q.top())Query(ls[x],v);
        }
        return;
    }
    signed main()
    {
        scanf("%lld%lld",&n,&k);
        for(ll i=1;i<=n;i++)
            scanf("%lld%lld",&p[i].x[0],&p[i].x[1]);
        ll rt;Build(rt,1,n,0);
        for(ll i=1;i<=2*k;i++)q.push(0);
        for(ll i=1;i<=n;i++)Query(1,p[i]);
        printf("%lld
    ",-q.top());
    }
    
  • 相关阅读:
    odoo14系列笔记-基本进销存(二)
    odoo14系列笔记-基本进销存(一)
    PVE另一种方法使用中科大的镜像服务器 NGINX反向代理
    git 国内加速
    VirtualBox开启套娃模式-打开嵌套 VT-x/AMD-V 功能
    K8S集群安装(基于DEIBAN,proxmox)
    JS语法 ES6、ES7、ES8、ES9、ES10、ES11、ES12新特性
    8个非常实用的Vue自定义指令
    require和import的区别
    js异步加载之defer、async、type=module
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14279329.html
Copyright © 2011-2022 走看看