zoukankan      html  css  js  c++  java
  • LibreOJ2043

    Portal

    Description

    给出平面上的(n(nleq10^5))个整点,求在欧几里得距离下第(k)远的点对之间的距离。

    Solution

    k-d树+堆。
    用小根堆维护当前找到的第(k)大,然后以堆顶元素为基准在k-d树上搜索即可。搜索到一个新值(d)时,将其与堆顶元素比较,若大于堆顶元素则弹出堆顶并加入(d)

    Code

    //「CQOI2016」K 远点对
    #include <algorithm>
    #include <cstdio>
    #include <queue>
    typedef long long lint;
    using namespace std;
    inline char gc()
    {
        static char now[1<<16],*s,*t;
        if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
        return *s++;
    }
    inline int read()
    {
        int x=0; char ch=gc();
        while(ch<'0'||'9'<ch) ch=gc();
        while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
        return x;
    }
    const int N=1e5+10;
    const int INF=0x3FFFFFFF;
    int n,k;
    int rt,ch[N][2];
    struct point{int c[2];} pt[N];
    struct zone{int c1[2],c2[2];} zn[N];
    void update(int p)
    {
        int ch0=ch[p][0],ch1=ch[p][1];
        for(int k=0;k<2;k++)
            zn[p].c1[k]=min(pt[p].c[k],min(zn[ch0].c1[k],zn[ch1].c1[k])),
            zn[p].c2[k]=max(pt[p].c[k],max(zn[ch0].c2[k],zn[ch1].c2[k]));
    }
    int D;
    bool operator<(point A,point B) {return A.c[D]<B.c[D];}
    void bldTr(int &p,int L,int R)
    {
        if(L>R) return;
        int mid=L+R>>1; p=mid;
        nth_element(pt+L,pt+mid,pt+R+1);
        bldTr(ch[p][0],L,mid-1),bldTr(ch[p][1],mid+1,R);
        update(p);
    }
    priority_queue< lint,vector<lint>,greater<lint> > Q;
    point A;
    lint dist(point B)
    {
        lint d=0;
        for(int k=0;k<2;k++) d+=1LL*(A.c[k]-B.c[k])*(A.c[k]-B.c[k]);
        return d;
    }
    lint dist(zone Z)
    {
        if(Z.c1[0]>Z.c2[0]) return 0;
        int d[2]; d[0]=d[1]=0;
        for(int k=0;k<2;k++) d[k]=max(abs(Z.c1[k]-A.c[k]),abs(Z.c2[k]-A.c[k]));
        return 1LL*d[0]*d[0]+1LL*d[1]*d[1];
    }
    void query(int p)
    {
        if(!p) return;
        lint d=dist(pt[p]);
        if(d>Q.top()) Q.pop(),Q.push(d);
        lint d0=dist(zn[ch[p][0]]),d1=dist(zn[ch[p][1]]);
        if(d0>Q.top()) query(ch[p][0]);
        if(d1>Q.top()) query(ch[p][1]);
    }
    int main()
    {
        n=read(),k=read();
        for(int i=1;i<=n;i++) pt[i].c[0]=read(),pt[i].c[1]=read();
        zn[0].c1[0]=zn[0].c1[1]=INF,zn[0].c2[0]=zn[0].c2[1]=-INF;
        bldTr(rt,1,n);
        for(int i=1;i<=k+k;i++) Q.push(0);
        for(int i=1;i<=n;i++) A=pt[i],query(rt);
        printf("%d
    ",Q.top());
        return 0;
    }
    

    P.S.

    网上好多题解是凸包+旋转卡壳...吓死我了∑(゚Д゚ノ)ノ

  • 相关阅读:
    AS将一个项目导入到另一个项目中
    Android Studio出现:Cause: unable to find valid certification path to requested target
    小米手机Toast带app名称
    PopupWindow 点击外部区域无法关闭的问题
    EditText inputType类型整理
    Fragment通过接口回调向父Activity传值
    Android selector一些坑
    Installation failed with message Failed to commit install session 634765663 with command cmd package
    旷视上海研究院机器人方向招聘
    语义SLAM的数据关联和语义定位(四)多目标测量概率模型
  • 原文地址:https://www.cnblogs.com/VisJiao/p/LOJ2043.html
Copyright © 2011-2022 走看看