就是用一些的方法把平面按点分成若干块,
方便你剪枝(这思路真暴力)
因为是剪枝暴力,复杂度是O(能过),可以拿来干超级多的事情
CQOI2016 : K远点对
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<queue>
#include<functional>
#define LL long long
#define maxn 100005
#define inf 0x3f3f3f3f
using namespace std;
int D,root,n,k;
struct Point
{
int d[2];
bool operator <(const Point &Ano)const{ return d[D]<Ano.d[D]; }
}P[maxn];
struct Area
{
int d[2],x[2],y[2],son[2];
}tr[maxn];
void upd(int now,int pre)
{
tr[now].x[0]=min(tr[now].x[0],tr[pre].x[0]);
tr[now].x[1]=max(tr[now].x[1],tr[pre].x[1]);
tr[now].y[0]=min(tr[now].y[0],tr[pre].y[0]);
tr[now].y[1]=max(tr[now].y[1],tr[pre].y[1]);
}
int build(int L,int R,int dir)
{
D=dir;int mid=(L+R)>>1;
nth_element(P+L,P+mid,P+1+R);
tr[mid].d[0]=tr[mid].x[0]=tr[mid].x[1]=P[mid].d[0];
tr[mid].d[1]=tr[mid].y[0]=tr[mid].y[1]=P[mid].d[1];
if(L<mid) tr[mid].son[0]=build(L,mid-1,dir^1),upd(mid,tr[mid].son[0]);
if(R>mid) tr[mid].son[1]=build(mid+1,R,dir^1),upd(mid,tr[mid].son[1]);
return mid;
}
inline LL sqr(int a)
{
return 1ll*a*a;
}
inline LL getdist(int now,int x,int y)
{
return max(sqr(x-tr[now].x[0]),sqr(x-tr[now].x[1]))+max(sqr(y-tr[now].y[0]),sqr(y-tr[now].y[1]));
}
priority_queue<LL,vector<LL>,greater<LL> >Q;
void Query(int now,int x,int y)
{
LL dist=sqr(x-tr[now].d[0])+sqr(y-tr[now].d[1]),dis[2];
Q.push(dist);
while(Q.size()>k) Q.pop();
dis[0]=tr[now].son[0] ? getdist(tr[now].son[0],x,y) : -inf;
dis[1]=tr[now].son[1] ? getdist(tr[now].son[1],x,y) : -inf;
dist=dis[0]<dis[1];
if(dis[dist]>=Q.top() || Q.size()<k) Query(tr[now].son[dist],x,y);
if(dis[dist^1]>=Q.top() || Q.size()<k) Query(tr[now].son[dist^1],x,y);
}
char ch;bool flag;
inline void get(int &res)
{
for(flag=0;!isdigit(ch=getchar());) if(ch=='-') flag=1;
for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0');
(flag) && (res=-res);
}
int main()
{
get(n),get(k);k*=2;
for(int i=1;i<=n;i++) get(P[i].d[0]),get(P[i].d[1]);
root=build(1,n,0);
for(int i=1;i<=n;i++)
Query(root,tr[i].d[0],tr[i].d[1]);
printf("%lld\n",Q.top());
}