• BZOJ 4520: [Cqoi2016]K远点对 KDtree + 估价函数 + 堆


    Description

    已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。

     

    Input

    输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点
    的坐标。1 < =  N < =  100000, 1 < =  K < =  100, K < =  N*(N−1)/2 , 0 < =  X, Y < 2^31。
     

    Output

    输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)

    题解: 用堆维护前 $k$ 远的距离,依次枚举每个点来更新即可.

    #include<bits/stdc++.h>
    #define ll long long 
    #define maxn 200000 
    #define inf 100000000000000 
    #define lson (t[x].ch[0])
    #define rson (t[x].ch[1]) 
    #define mid ((l+r)>>1) 
    using namespace std;
    void debug()
    {
        printf("no_problem
    ");   
    }    
    int n,K,d,root; 
    void setIO(string s)
    {
        string in=s+".in"; 
        freopen(in.c_str(),"r",stdin);  
    }
    priority_queue<ll,vector<ll>, greater<ll> >Q; 
    struct Node
    {
        int p[2],ch[2],minv[2],maxv[2]; 
    }t[maxn],T; 
    bool cmp(Node a,Node b)
    {
        return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d]; 
    }
    void pushup(int x,int y)
    {
        t[x].minv[0]=min(t[x].minv[0],t[y].minv[0]); 
        t[x].maxv[0]=max(t[x].maxv[0],t[y].maxv[0]); 
        t[x].minv[1]=min(t[x].minv[1],t[y].minv[1]); 
        t[x].maxv[1]=max(t[x].maxv[1],t[y].maxv[1]);   
    }
    int build(int l,int r,int o)
    {
        d=o;
        nth_element(t+l,t+mid,t+1+r,cmp); 
        t[mid].minv[0]=t[mid].maxv[0]=t[mid].p[0]; 
        t[mid].minv[1]=t[mid].maxv[1]=t[mid].p[1]; 
        t[mid].ch[0]=t[mid].ch[1]=0; 
        if(mid>l)
        {
            t[mid].ch[0]=build(l,mid-1,o^1); 
            pushup(mid,t[mid].ch[0]); 
        }
        if(r>mid)
        {
            t[mid].ch[1]=build(mid+1,r,o^1); 
            pushup(mid,t[mid].ch[1]); 
        }
        return mid; 
    } 
    ll sq(ll x)
    { 
        return x * x; 
    }
    ll getmax(int x)
    {
        ll ans=0;
        for(int i=0;i<2;++i)
        {
            ans+=max( sq(1ll*(t[x].minv[i]-T.p[i])), sq(1ll*(t[x].maxv[i]-T.p[i])) ); 
        }
        return ans; 
    }
    void solve(int x,int x1,int y1)
    {
        ll dn=getmax(x), cur=sq(1ll*(t[x].p[0]-x1)) + sq(1ll*(t[x].p[1]-y1));      
        if(dn <= Q.top()) return;  
        if(cur>Q.top())           
        {
            Q.pop(); 
            Q.push(cur); 
        }                       
        ll dl=lson ? getmax(lson) : -inf; 
        ll dr=rson ? getmax(rson) : -inf; 
        if(dl>dr)
        {
            if(dl > Q.top()) solve(lson, x1, y1);   
            if(dr > Q.top()) solve(rson, x1, y1); 
        }
        else 
        {
            if(dr > Q.top()) solve(rson, x1, y1); 
            if(dl > Q.top()) solve(lson, x1, y1); 
        }
    }
    int main()
    {
        // setIO("input");
        scanf("%d%d",&n,&K); 
        K<<=1;  
        for(int i=1;i<=n;++i) scanf("%d%d",&t[i].p[0],&t[i].p[1]);  
        root=build(1,n,0); 
        for(int i=1;i<=K;++i) Q.push(0); 
        for(int i=1;i<=n;++i)
        {
            T.p[0]=t[i].p[0]; 
            T.p[1]=t[i].p[1]; 
            solve(root,T.p[0],T.p[1]);  
        }   
        printf("%lld
    ",Q.top()); 
        return 0;    
    }
    

      

  • 相关阅读:
    [kuangbin带你飞]专题十二 基础DP1 E
    hdu 1203 I NEED A OFFER! (01背包)
    hdu 2602 Bone Collector (01背包)
    hdu 4513 吉哥系列故事——完美队形II (manacher)
    hdu 2203 亲和串 (KMP)
    hdu 1686 Oulipo (KMP)
    hdu 1251 统计难题 (字典树)
    hdu 2846 Repository (字典树)
    hdu 1711 Number Sequence (KMP)
    poj 3461 Oulipo(KMP)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11059499.html
Copyright © 2020-2023  润新知