[K-D Tree] 天使玩偶/SJY摆棋子
洛谷 P4169这题第11个点卡不过去,BZOJ 2648这题过了= =
Code
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define RG register int
#define LL long long
template<typename elemType>
inline void Read(elemType &T){
elemType X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
T=(w?-X:X);
}
namespace KDT{
const int maxn=1000010;
const int maxk=2;//K维空间
const int INF=2147483647;
int D;
struct Point{
int d[2];
bool operator<(const Point &a)const{return d[D]<a.d[D];}
};
struct KD_Tree{
int root,index;
Point point[maxn];
struct KDTree_Node{
int d[maxk],son[2],x[2],y[2];
};
KDTree_Node node[maxn];
void push_up(int u,int v){// u-fa v-son
node[u].x[0]=min(node[u].x[0],node[v].x[0]);
node[u].x[1]=max(node[u].x[1],node[v].x[1]);
node[u].y[0]=min(node[u].y[0],node[v].y[0]);
node[u].y[1]=max(node[u].y[1],node[v].y[1]);
}
int get_Dist(int u,int _x,int _y){//查询(_x,_y)到当前区域u的最小曼哈顿距离
return max(node[u].x[0]-_x,0)+max(_x-node[u].x[1],0)+max(node[u].y[0]-_y,0)+max(_y-node[u].y[1],0);
}
int build_KD_Tree(int L,int R,int d){
D=d;int u=(L+R)>>1;
std::nth_element(point+L+1,point+u,point+R+1);
node[u].d[0]=node[u].x[0]=node[u].x[1]=point[u].d[0];
node[u].d[1]=node[u].y[0]=node[u].y[1]=point[u].d[1];
if(L<u){node[u].son[0]=build_KD_Tree(L,u-1,d^1);push_up(u,node[u].son[0]);}
if(u<R){node[u].son[1]=build_KD_Tree(u+1,R,d^1);push_up(u,node[u].son[1]);}
return u;
}
void build(int n){index=n;D=0;root=build_KD_Tree(1,n,0);}
void insert_Point(int _x,int _y){
++index;D=0;
point[index].d[0]=_x;
point[index].d[1]=_y;
node[index].d[0]=node[index].x[0]=node[index].x[1]=_x;
node[index].d[1]=node[index].y[0]=node[index].y[1]=_y;
for(RG p=root;p;D^=1){
push_up(p,index);
int &nxt=node[p].son[node[index].d[D]>=node[p].d[D]];
if(!nxt){nxt=index;return;}
else p=nxt;
}
}
void query(int u,int _x,int _y,int &res){//查询到(_x,_y)曼哈顿距离最近的点的距离
int temp=abs(node[u].d[0]-_x)+abs(node[u].d[1]-_y);
int d[2];
if(node[u].son[0]) d[0]=get_Dist(node[u].son[0],_x,_y);
else d[0]=INF;
if(node[u].son[1]) d[1]=get_Dist(node[u].son[1],_x,_y);
else d[1]=INF;
res=min(res,temp);
int v=d[0]>=d[1];
if(d[v]<res) query(node[u].son[v],_x,_y,res);v^=1;
if(d[v]<res) query(node[u].son[v],_x,_y,res);
return;
}
};
};
int N,M;
KDT::KD_Tree Tree;
int main(){
Read(N);Read(M);
Tree.index=N;
for(RG i=1;i<=N;++i){
Read(Tree.point[i].d[0]);
Read(Tree.point[i].d[1]);
}
Tree.build(N);
while(M--){
int opt,x,y;
Read(opt);Read(x);Read(y);
if(opt==1) Tree.insert_Point(x,y);
else{
int Ans=KDT::INF;
Tree.query(Tree.root,x,y,Ans);
printf("%d\n",Ans);
}
}
return 0;
}