1. 程式人生 > >LibreOJ2043 - 「CQOI2016」K 遠點對

LibreOJ2043 - 「CQOI2016」K 遠點對

targe prior vector line std tar 比較 namespace for

Portal

Description

給出平面上的\(n(n\leq10^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\n",Q.top()); return 0; }

P.S.

網上好多題解是凸包+旋轉卡殼...嚇死我了∑(?Д?ノ)ノ

LibreOJ2043 - 「CQOI2016」K 遠點對