• [CQOI2016]K远点对(KD-Tree)


    暴力的做法应该是这样的,维护大小为k的堆,每次插入两点间距离并弹出堆顶。

    然后这个做法显然是可以KD-Tree优化的,建立KD-Tree,然后如果该平面内最远点小于堆顶,则直接退出。就当做是复习很久没做的KD-Tree了。

    不过有一个细节要注意,求最远点对,(1,2)->(2,1)算一对,所以堆的大小应该是2*k

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+7;
    struct point{ll d[2];}a[N];
    struct node{int mn[2],mx[2],lc,rc;point a;}t[N];
    priority_queue<ll,vector<ll>,greater<ll> >q;
    int n,m,rt,D;
    bool operator<(point a,point b){return a.d[D]<b.d[D];}
    void pushup(int x,int y)
    {
        t[x].mn[0]=min(t[x].mn[0],t[y].mn[0]);
        t[x].mn[1]=min(t[x].mn[1],t[y].mn[1]);
        t[x].mx[0]=max(t[x].mx[0],t[y].mx[0]);
        t[x].mx[1]=max(t[x].mx[1],t[y].mx[1]);
    }
    void build(int&k,int l,int r,int d)
    {
        k=0;
        if(l>r)return;
        D=d;
        int mid=l+r>>1;
        nth_element(a+l,a+mid,a+r+1);
        k=mid;
        t[k].mn[0]=t[k].mx[0]=t[k].a.d[0]=a[k].d[0];
        t[k].mn[1]=t[k].mx[1]=t[k].a.d[1]=a[k].d[1];
        build(t[k].lc,l,mid-1,d^1);
        if(t[k].lc)pushup(k,t[k].lc);
        build(t[k].rc,mid+1,r,d^1);
        if(t[k].rc)pushup(k,t[k].rc);
    }
    ll getdis(point a,point b)
    {return(a.d[0]-b.d[0])*(a.d[0]-b.d[0])+(a.d[1]-b.d[1])*(a.d[1]-b.d[1]);}
    ll getdis2(point a,node b)
    {
        ll ret=0;
        ret=max(ret,getdis(a,(point){b.mn[0],b.mn[1]}));
        ret=max(ret,getdis(a,(point){b.mn[0],b.mx[1]}));
        ret=max(ret,getdis(a,(point){b.mx[0],b.mn[1]}));
        ret=max(ret,getdis(a,(point){b.mx[0],b.mx[1]}));
        return ret;
    }
    void query(int k,point a)
    {
        ll dis=getdis(a,t[k].a);
        if(dis>q.top())q.pop(),q.push(dis);
        if(t[k].lc)
        {
            dis=getdis2(a,t[t[k].lc]);
            if(dis>q.top())query(t[k].lc,a);
        }
        if(t[k].rc)
        {
            dis=getdis2(a,t[t[k].rc]);
            if(dis>q.top())query(t[k].rc,a);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].d[0],&a[i].d[1]);
        build(rt,1,n,0);
        for(int i=1;i<=m*2;i++)q.push(0);
        for(int i=1;i<=n;i++)query(rt,a[i]);
        printf("%lld",q.top());
    }
    View Code
  • 相关阅读:
    如何判断某个变量是否是数组?
    mac vscode编辑器的快捷键
    vue require.context()动态文件引入
    在vue项目上使用less
    nrm是什么
    对象的扩展方法
    es5严格模式
    微信公众号定位不准问题
    layer使用iframe的路径不对问题
    form表单中reset对js赋值的表单象无法重置问题
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/11179344.html
Copyright © 2020-2023  润新知