P4357-[CQOI2016]K远点对【K-Dtree】
生活随笔
收集整理的這篇文章主要介紹了
P4357-[CQOI2016]K远点对【K-Dtree】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P4357
題目大意
平面上給出nnn個點,求第kkk遠的點對距離。
解題思路
K-Dtree\text{K-Dtree}K-Dtree的模板題,但是這里只有二維,大概是每次根據(jù)一個維度把nnn個點分成兩半像線段樹一樣丟到下面繼續(xù)分治的思想來構建一棵樹。
那么這樣分割出來的每個節(jié)點的點分割了自己的矩形范圍成了兩個子節(jié)點的矩形范圍。
這題的話我們就先構造出K-Dtree\text{K-Dtree}K-Dtree然后記錄一下每個節(jié)點的矩形范圍。
之后開一個小根堆,里面先丟2k2k2k個000(因為會算重),然后每次找到的一個點對距離如果比堆頂大就要換一個新的進堆就好了。
這樣就保證了堆里存的是前2k2k2k大的點對了,之后每次用矩形范圍判斷一下新的答案是否在某個子節(jié)點的矩形里面。
沒有插入所以可以不用暴力重構
code
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<queue> #define ll long long #define pw(x) ((x)*(x)) using namespace std; const ll N=4e5+10,inf=1e18; struct point{ll x[2]; }w[N],p[N]; ll n,k,cnt,opt,mx[N][2],mi[N][2],ls[N],rs[N]; priority_queue<ll> q; bool cmp(point x,point y) {return x.x[opt]<y.x[opt];} ll gdis(point x,point y) {return pw(x.x[0]-y.x[0])+pw(x.x[1]-y.x[1]);} ll limd(point x,ll y) {return max(pw(x.x[0]-mx[y][0]),pw(x.x[0]-mi[y][0]))+max(pw(x.x[1]-mx[y][1]),pw(x.x[1]-mi[y][1]));} void PushUp(ll x){ll l=ls[x],r=rs[x];mx[x][0]=mi[x][0]=w[x].x[0];mx[x][1]=mi[x][1]=w[x].x[1];if(l){for(ll i=0;i<2;i++)mx[x][i]=max(mx[x][i],mx[l][i]);for(ll i=0;i<2;i++)mi[x][i]=min(mi[x][i],mi[l][i]);}if(r){for(ll i=0;i<2;i++)mx[x][i]=max(mx[x][i],mx[r][i]);for(ll i=0;i<2;i++)mi[x][i]=min(mi[x][i],mi[r][i]);}return; } void Build(ll &x,ll l,ll r,ll z){if(l>r)return;x=++cnt;ll mid=(l+r)>>1;opt=z;nth_element(p+l,p+mid,p+r+1,cmp);w[x]=p[mid];Build(ls[x],l,mid-1,z^1);Build(rs[x],mid+1,r,z^1);PushUp(x);return; } void Query(ll x,point v){if(!x)return;ll dl=-inf,dr=-inf;if(ls[x])dl=limd(v,ls[x]);if(rs[x])dr=limd(v,rs[x]);ll dis=gdis(w[x],v);if(dis>-q.top())q.pop(),q.push(-dis);if(dl>dr){if(dl>-q.top())Query(ls[x],v);if(dr>-q.top())Query(rs[x],v);}else{if(dr>-q.top())Query(rs[x],v);if(dl>-q.top())Query(ls[x],v);}return; } signed main() {scanf("%lld%lld",&n,&k);for(ll i=1;i<=n;i++)scanf("%lld%lld",&p[i].x[0],&p[i].x[1]);ll rt;Build(rt,1,n,0);for(ll i=1;i<=2*k;i++)q.push(0);for(ll i=1;i<=n;i++)Query(1,p[i]);printf("%lld\n",-q.top()); } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的P4357-[CQOI2016]K远点对【K-Dtree】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P5212-SubString【LCT,
- 下一篇: 安卓平板真的不如iPad安卓平板真的不如