bzoj 1941: [Sdoi2010]Hide and Seek
作者:互联网
KD_tree的估价查询
/************************************************************** Problem: 1941 User: lxy8584099 Language: C++ Result: Accepted Time:2952 ms Memory:32080 kb ****************************************************************/ /* 枚举每个点 找最大最小距离 更新 findmax/min函数只是一个估价函数 选择最优的先进行递归 可能次优的就不会进入递归了 max里所有维取最大值进行计算距离 返回一个估价值 min里的股价方式有点玄学。。。好象是卡在mx和mn之间的时候越优 估价方式往往决定了KD_tree的查询效率。 */ #include<cmath> #include<cstdio> #include<algorithm> #define ll long long #define inf (0x3fffffff) using namespace std; const int N=5e5+50; int n,now,rt,ans; struct data { int d[2],mx[2],mn[2],lc,rc; friend bool operator < (data a,data b) {return a.d[now]<b.d[now];} }dat[N],t[N],p; void getmax(int&a,int b){if(a<b)a=b;} void getmin(int&a,int b){if(a>b)a=b;} void pushup(int x) { for(int i=0;i<2;i++) { int lc=t[x].lc,rc=t[x].rc; t[x].mn[i]=t[x].mx[i]=t[x].d[i]; if(lc) getmin(t[x].mn[i],t[lc].mn[i]), getmax(t[x].mx[i],t[lc].mx[i]); if(rc) getmin(t[x].mn[i],t[rc].mn[i]), getmax(t[x].mx[i],t[rc].mx[i]); } } int build(int l,int r,int pl) { now=pl; int mid=(l+r)>>1; nth_element(dat+l,dat+mid,dat+r+1); t[mid]=dat[mid]; if(l<mid) t[mid].lc=build(l,mid-1,!pl); if(r>mid) t[mid].rc=build(mid+1,r,!pl); pushup(mid); return mid; } int dist(data a,data b) { return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]); } int findmax(data a) { int res=0; for(int i=0;i<2;i++) res+=max(abs(p.d[i]-a.mx[i]),abs(p.d[i]-a.mn[i])); return res; } void querymax(int x) { getmax(ans,dist(t[x],p)); int lc=t[x].lc,rc=t[x].rc; int ml=-inf,mr=-inf; if(lc) ml=findmax(t[lc]); if(rc) mr=findmax(t[rc]); if(lc>rc) { if(ml>ans) querymax(lc); if(mr>ans) querymax(rc); } else { if(mr>ans) querymax(rc); if(ml>ans) querymax(lc); } } int findmin(data a) { int res=0; for(int i=0;i<2;i++) res+=max(p.d[i]-a.mx[i],0), res+=max(a.mn[i]-p.d[i],0); return res; } void querymin(int x) { int tmp=dist(t[x],p); if(tmp) getmin(ans,tmp); int lc=t[x].lc,rc=t[x].rc; int ml=inf,mr=inf; if(lc) ml=findmin(t[lc]); if(rc) mr=findmin(t[rc]); if(ml<mr) { if(ml<ans) querymin(lc); if(mr<ans) querymin(rc); } else { if(mr<ans) querymin(rc); if(ml<ans) querymin(lc); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&dat[i].d[0],&dat[i].d[1]); rt=build(1,n,0); int end=inf; for(int i=1;i<=n;i++) { int minn,maxn; p=dat[i]; ans=-inf; querymax(rt); maxn=ans; ans=inf; querymin(rt); minn=ans; getmin(end,maxn-minn); } printf("%d\n",end); return 0; }
标签:dat,rc,int,data,1941,mid,Sdoi2010,ans,Seek 来源: https://www.cnblogs.com/lxy8584099/p/10427725.html