题目大意:给出平面上一些点,要求支持插入点,查询离某个点的最近点的曼哈顿距离。
KDTree裸题
https://zhuanlan.zhihu.com/p/22557068
#include <cstdio>
#include <algorithm>
#define N 500005
#define INF 2000000000
using namespace std;
const double alpha=0.7;
struct Point {
int x,y;
Point() {}
Point(int _x,int _y):
x(_x),y(_y) {}
int operator | (const Point& rhs) const {
return abs(x-rhs.x)+abs(y-rhs.y);
}
void scan() { scanf("%d%d",&x,&y); }
}a[N];
bool cmpx(Point lhs,Point rhs) { return lhs.x<rhs.x; }
bool cmpy(Point lhs,Point rhs) { return lhs.y<rhs.y; }
bool (*cmp[2])(Point,Point)={cmpx,cmpy};
Point min(const Point& lhs,const Point& rhs) {
return Point(min(lhs.x,rhs.x),min(lhs.y,rhs.y));
}
Point max(const Point& lhs,const Point& rhs) {
return Point(max(lhs.x,rhs.x),max(lhs.y,rhs.y));
}
int get_mindist(Point o,Point maxx,Point minn) {
int tmp=0;
if(cmp[0](o,minn)) tmp+=minn.x-o.x;
if(cmp[0](maxx,o)) tmp+=o.x-maxx.x;
if(cmp[1](o,minn)) tmp+=minn.y-o.y;
if(cmp[1](maxx,o)) tmp+=o.y-maxx.y;
return tmp;
}
struct Node {
Node* ch[2];
Point pos,maxx,minn;
int siz,mode;
Node() {}
Node(Point _pos,bool _mode):mode(_mode) {
pos=maxx=minn=_pos;
ch[0]=ch[1]=NULL;
siz=1;
}
void* operator new(size_t) {
static Node *mempool,*C;
if(mempool==C) mempool=(C=new Node[1<<20])+(1<<20);
return C++;
}
void maintain() {
siz=1;
for(int i=0;i<2;i++)
if(ch[i]) {
siz+=ch[i]->siz;
maxx=max(maxx,ch[i]->maxx);
minn=min(minn,ch[i]->minn);
}
return ;
}
bool check() {
for(int i=0;i<2;i++)
if(ch[i] && ch[i]->siz>siz*alpha)
return true;
return false;
}
}*root;
void build(Node*& o,int l,int r,int mode) {
if(l>r) return ;
int mid=l+r>>1;
if(l==r) {
o=new Node(a[mid],mode);
return ;
}
nth_element(a+l,a+mid,a+r+1,cmp[mode]);
o=new Node(a[mid],mode);
build(o->ch[0],l,mid-1,mode^1);
build(o->ch[1],mid+1,r,mode^1);
o->maintain();
return ;
}
Node** s[N*2];
int top;
void Insert(Node*& o,Point pos,int mode) {
if(!o) {
o=new Node(pos,mode);
return ;
}
int d=cmp[mode](pos,o->pos);
Insert(o->ch[d^1],pos,mode^1);
o->maintain();
if(o->check()) s[++top]=&o;
return ;
}
int tot;
void Delete(Node*& o) {
if(o->ch[0]) Delete(o->ch[0]);
a[++tot]=o->pos;
if(o->ch[1]) Delete(o->ch[1]);
return ;
}
void rebuild(Node*& o) {
top=tot=0;
bool mode=o->mode;
Delete(o);
build(o,1,tot,mode);
return ;
}
int ans;
void query(Node* o,Point pos) {
ans=min(ans,pos|o->pos);
int minn[2];
for(int i=0;i<2;i++)
minn[i]=o->ch[i]?get_mindist(pos,o->ch[i]->maxx,o->ch[i]->minn):INF;
if(minn[0]<minn[1]) {
if(o->ch[0] && minn[0]<ans) query(o->ch[0],pos);
if(o->ch[1] && minn[1]<ans) query(o->ch[1],pos);
}
else {
if(o->ch[1] && minn[1]<ans) query(o->ch[1],pos);
if(o->ch[0] && minn[0]<ans) query(o->ch[0],pos);
}
return ;
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) a[i].scan();
build(root,1,n,0);
while(m--) {
int mode;
Point o;
scanf("%d",&mode);
o.scan();
if(mode==1) {
top=0;
Insert(root,o,root->mode);
if(top) rebuild(*s[top]);
}
else {
ans=INF;
query(root,o);
printf("%d\n",ans);
}
}
return 0;
}