P4357 [CQOI2016]K遠點對(KDTree)
阿新 • • 發佈:2018-12-09
又一次產生了KDTree本質就是爆搜的感覺……
大概就類似於p4169,只不過是從最近點對變成了第\(k\)遠點對
我們開一個小根堆,裡面放\(k\)個元素,起初全為\(0\),然後每一次都把點對的距離和堆頂比較,如果點對距離大於就彈出堆頂並讓這個點對入堆,那麼最後堆頂就是答案了
於是我們可以列舉每一個點,然後在KDTree上dfs就行了
然後因為每個點對會被列舉兩次,所以小根堆的大小實際上要開\(2*k\)
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #define inf 0x3f3f3f3f #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i) #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;} template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} ll read(){ R ll res,f=1;R char ch; while((ch=getc())>'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<ll,vector<ll>,greater<ll> >q; inline bool operator <(const node &a,const node &b){return a.v[K]<b.v[K];} void upd(int p){ int l=tr[p].l,r=tr[p].r; fp(i,0,1){ tr[p].mn[i]=tr[p].mx[i]=tr[p].v[i]; if(l)cmin(tr[p].mn[i],tr[l].mn[i]),cmax(tr[p].mx[i],tr[l].mx[i]); if(r)cmin(tr[p].mn[i],tr[r].mn[i]),cmax(tr[p].mx[i],tr[r].mx[i]); } } int build(int l,int r,int k){ K=k;int mid=(l+r)>>1;nth_element(tr+l,tr+mid,tr+r+1); if(l<mid)tr[mid].l=build(l,mid-1,k^1); if(mid<r)tr[mid].r=build(mid+1,r,k^1); upd(mid);return mid; } inline ll sqr(ll x){return x*x;} inline ll ck(ll x,ll y,int p){ return max(sqr(tr[p].mn[0]-x),sqr(tr[p].mx[0]-x))+max(sqr(tr[p].mn[1]-y),sqr(tr[p].mx[1]-y)); } inline ll dis(ll x,ll y,ll xx,ll yy){ return sqr(x-xx)+sqr(y-yy); } void query(int p){ ll dl=-inf,dr=-inf,dd=dis(tr[p].v[0],tr[p].v[1],S.v[0],S.v[1]); if(tr[p].l)dl=ck(S.v[0],S.v[1],tr[p].l); if(tr[p].r)dr=ck(S.v[0],S.v[1],tr[p].r); if(dd>q.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; }