P4357 [CQOI2016]K远点对

题意:给定平面中的 (n) 个点,求第 (K) 远的点对之间的距离,(nleq 1e5,Kleq min(100,frac{n imes (n-1)}{2}))
题解:kd-tree + priority_queue
size(2 imes K) 的小根堆记录当前 前 (2 imes K) 远的点对,并以此为在搜索时剪枝的依据。

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#define R register int
#define ll long long
using namespace std;
namespace Luitaryi {
static char B[1<<15],*S=B,*T=B;
#define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
inline int g() { R x=0,f=1;
  register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
  do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=100010,Inf=0x3f3f3f3f;
int n,m,rt,D;
struct P { int d[2]; 
  inline int& operator [](int src) {return d[src];}
  inline bool operator < (const P& that) const 
    {return d[D]<that.d[D];}
}p[N],s;
priority_queue<ll,vector<ll>,greater<ll> > q;
struct node { 
  int lc,rc,mx[2],mn[2]; P p;
  #define ls (t[tr].lc)
  #define rs (t[tr].rc)
  #define mx(tr,i) (t[tr].mx[i])
  #define mn(tr,i) (t[tr].mn[i])
  #define P(tr,i) (t[tr].p.d[i])
}t[N];
inline void upd(int tr) {
  for(R i=0;i<2;++i) {
    mx(tr,i)=max(mx(tr,i),max(mx(ls,i),mx(rs,i)));
    mn(tr,i)=min(mn(tr,i),min(mn(ls,i),mn(rs,i)));
  }
}
inline void build(int& tr,int l,int r,int dim) {
  R md=l+r>>1; tr=md; D=dim,nth_element(p+l,p+md,p+r+1);
  t[tr].p=p[md]; for(R i=0;i<2;++i) mx(tr,i)=mn(tr,i)=P(tr,i);
  if(l<md) build(ls,l,md-1,dim^1);
  if(md<r) build(rs,md+1,r,dim^1); upd(tr);
}
#define sqr(x) ((ll)(x)*(x))
inline ll cal(P p) {
  return sqr(p[0]-s[0])+sqr(p[1]-s[1]);
}
inline ll cal(int tr) {
  return max(sqr(s[0]-mn(tr,0)),sqr(s[0]-mx(tr,0)))
        +max(sqr(s[1]-mn(tr,1)),sqr(s[1]-mx(tr,1))); 
}
inline void query(int tr) {
  register ll dis=cal(t[tr].p),ldis=-Inf,rdis=-Inf;
  if(dis>q.top()) q.pop(),q.push(dis);
  if(ls) ldis=cal(ls); if(rs) rdis=cal(rs);
  if(ldis>rdis) {
    if(ldis>q.top()) query(ls);
    if(rdis>q.top()) query(rs);
  } else {
    if(rdis>q.top()) query(rs);
    if(ldis>q.top()) query(ls);
  }
}
inline void main() {
  n=g(),m=g()*2; mx(0,0)=mx(0,1)=-Inf,mn(0,0)=mn(0,1)=Inf;
  for(R i=1;i<=n;++i) p[i].d[0]=g(),p[i].d[1]=g();
  build(rt,1,n,0); for(R i=1;i<=m;++i) q.push(0);
  for(R i=1;i<=n;++i) s=p[i],query(rt);
  printf("%lld
",q.top());
}
} signed main() {Luitaryi::main(); return 0;}
原文地址:https://www.cnblogs.com/Jackpei/p/12070237.html