P4357 [CQOI2016]K远点对(KDTree)

传送门

又一次产生了KDTree本质就是爆搜的感觉……
大概就类似于p4169,只不过是从最近点对变成了第\(k\)远点对
我们开一个小根堆,里面放\(k\)个元素,起初全为\(0\),然后每一次都把点对的距离和堆顶比较,如果点对距离大于就弹出堆顶并让这个点对入堆,那么最后堆顶就是答案了
于是我们可以枚举每一个点,然后在KDTree上dfs就行了
然后因为每个点对会被枚举两次,所以小根堆的大小实际上要开\(2*k\)

//minamoto
#include
#define R register
#define ll long long
#define inf 0x3f3f3f3f
#define fp(i,a,b) for(R int i=a,I=b+1;iI;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
templateinline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
templateinline bool cmax(T&a,const T&b){return a'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=1e5+5;
struct node{ll v[2],mn[2],mx[2];int l,r;}tr[N],S;
int n,m,K,rt;priority_queue,greater >q;
inline bool operator <(const node &a,const node &b){return a.v[K]>1;nth_element(tr+l,tr+mid,tr+r+1);
    if(lq.top())q.pop(),q.push(dd);
    if(dl>dr){
        if(dl>q.top())query(tr[p].l);
        if(dr>q.top())query(tr[p].r);
    }else{
        if(dr>q.top())query(tr[p].r);
        if(dl>q.top())query(tr[p].l);
    }
}
int main(){
//  freopen("testdata.in","r",stdin);
    n=read(),m=read();fp(i,1,n)tr[i].v[0]=read(),tr[i].v[1]=read();
    rt=build(1,n,0);fp(i,1,m*2)q.push(0);
    fp(i,1,n)S.v[0]=tr[i].v[0],S.v[1]=tr[i].v[1],query(rt);
    printf("%lld\n",q.top());return 0;
}

转载于:https://www.cnblogs.com/bztMinamoto/p/10093487.html

你可能感兴趣的:(P4357 [CQOI2016]K远点对(KDTree))