BZOJ4520: [Cqoi2016]K远点对
题解: 求一个点第K远的点对我们可以通过KDtree+堆来维护 即可 这题查询的是所有点对中的第K远 所以我们考虑边加入点 边维护堆即可
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=1e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int n,k,rt,d; typedef struct node{ int p[2],minn[2],maxx[2],c[2]; friend bool operator<(node aa,node bb){ if(aa.p[d]!=bb.p[d])return aa.p[d]<bb.p[d]; return aa.p[d^1]<bb.p[d^1]; } }node; node a[MAXN]; void up(int x,int y){ inc(i,0,1)a[x].minn[i]=min(a[x].minn[i],a[y].minn[i]),a[x].maxx[i]=max(a[x].maxx[i],a[y].maxx[i]); } int built(int l,int r,int now){ int mid=(l+r)>>1; d=now;nth_element(a+l,a+mid,a+r+1); inc(i,0,1)a[mid].minn[i]=a[mid].maxx[i]=a[mid].p[i]; a[mid].c[0]=a[mid].c[1]=0; if(l<mid)a[mid].c[0]=built(l,mid-1,now^1),up(mid,a[mid].c[0]); if(r>mid)a[mid].c[1]=built(mid+1,r,now^1),up(mid,a[mid].c[1]); return mid; } inline void insert(int x) { int *t=&rt; d=0; while(*t)up(*t,x),t=&a[*t].c[a[x].p[d]>a[*t].p[d]],d=d^1; *t=x; } typedef struct Tmp{ ll dis; friend bool operator<(Tmp aa,Tmp bb){return aa.dis>bb.dis;} }Tmp; priority_queue<Tmp>que; node t; ll dist(node x,node y){ ll res=0; inc(i,0,1)res+=1LL*(x.p[i]-y.p[i])*(x.p[i]-y.p[i]); return res; } ll get_ans(node x,node y){ ll res=0; inc(i,0,1)res+=max(1LL*(y.p[i]-x.minn[i])*(y.p[i]-x.minn[i]),1LL*(y.p[i]-x.maxx[i])*(y.p[i]-x.maxx[i])); return res; } void querty(int x){ if(!x)return ; ll res=dist(a[x],t); if(res>(que.top()).dis){que.pop();que.push((Tmp){res});} ll dl=(a[x].c[0])?get_ans(a[a[x].c[0]],t):-1; ll dr=(a[x].c[1])?get_ans(a[a[x].c[1]],t):-1; if(dl>dr){ if(dl>(que.top()).dis)querty(a[x].c[0]); if(dr>(que.top()).dis)querty(a[x].c[1]); } if(dr>dl){ if(dr>(que.top()).dis)querty(a[x].c[1]); if(dl>(que.top()).dis)querty(a[x].c[0]); } } int main(){ n=read();k=read(); inc(i,1,k)que.push((Tmp){-1}); inc(i,1,n){ a[i].p[0]=read();a[i].p[1]=read();t=a[i]; querty(rt); a[i].c[0]=a[i].c[1]=0; a[i].maxx[0]=a[i].minn[0]=a[i].p[0]; a[i].maxx[1]=a[i].minn[1]=a[i].p[1]; insert(i); } printf("%lld\n",(que.top()).dis); }
4520: [Cqoi2016]K远点对
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1302 Solved: 718
[Submit][Status][Discuss]
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 远点对的距离的平方(一定是个整数)。
Sample Input
10 5
0 0
0 1
1 0
1 1
2 0
2 1
1 2
0 2
3 0
3 1
0 0
0 1
1 0
1 1
2 0
2 1
1 2
0 2
3 0
3 1
Sample Output
9