Description
为了写论文,Alex经常要整理大量的数据。 这一次,Alex面临一个严峻的考验:他需要实现一个数据结构来维护一个点集。
现在,二维平面上有N个点。Alex 需要实现以下三种操作:
1. 在点集里添加一个点;
2. 给出一个点,查询它到点集里所有点的曼哈顿距离的最小值;
3. 给出一个点,查询它到点集里所有点的曼哈顿距离的最大值。
两个点的曼哈顿距离定义为它们的横坐标差的绝对值与纵坐标差的绝对值的和。这么困难的问题,Alex当然不会做,只好再次请你帮忙了。
Input
第一行包含一个整数N,表示点集最初的点数。
接下来N行,每行两个整数,依次表示每个点的横坐标和纵坐标。
第N+2行包含一个整数Q,表示询问的数目。
接下来Q行,每行三个整数,依次表示询问的类型,点的横坐标和纵坐标。0类型表示添加一个点,1类型表示查询到该点的曼哈顿距离的最小值,2类型表示查询最大值。
1 ≤ N, Q ≤ 100,000,点的坐标是不超过10^9的非负整数
Output
输出若干行,依次表示每个查询操作的答案。
将点集所有点预处理建成二维kd树,即可查询最近/远点对。
每次插入点时可以自底向上修改。
#include<cstdio> #include<algorithm> const int inf=2147483647; inline int read(){ int x=0,c=getchar(); while(c>57||c<48)c=getchar(); while(c>47&&c<58)x=x*10+c-48,c=getchar(); return x; } int ans,X[2]; inline void mins(int&a,int b){if(a>b)a=b;} inline void maxs(int&a,int b){if(a<b)a=b;} inline int max(int a){return a>0?a:0;} struct node{ int x[2],mn0,mn1,mx0,mx1,id,d,sz; node*c0,*c1,*f; inline void set(int x1,int x2,int i){ x[0]=x1; x[1]=x2; mn0=mn1=inf; mx0=mx1=-1; id=i; sz=d=0; } inline void upd(int x1,int x2){ mins(mn0,x1); mins(mn1,x2); maxs(mx0,x1); maxs(mx1,x2); ++sz; } inline int minv(){ if(!this||!sz)return inf; return max(mn0-X[0])+max(X[0]-mx0)+max(mn1-X[1])+max(X[1]-mx1); } inline int maxv(){ if(!this||!sz)return -1; return max(X[0]-mn0)+max(mx0-X[0])+max(X[1]-mn1)+max(mx1-X[1]); } void getmin(){ int a1=inf,a2=inf; if(d)mins(ans,abs(x[0]-X[0])+abs(x[1]-X[1])); mins(a1,c0->minv()); mins(a2,c1->minv()); if(a1<a2){ if(a1<ans)c0->getmin(); if(a2<ans)c1->getmin(); }else{ if(a2<ans)c1->getmin(); if(a1<ans)c0->getmin(); } } void getmax(){ int a1=-1,a2=-1; if(d)maxs(ans,abs(x[0]-X[0])+abs(x[1]-X[1])); maxs(a1,c0->maxv()); maxs(a2,c1->maxv()); if(a1>a2){ if(a1>ans)c0->getmax(); if(a2>ans)c1->getmax(); }else{ if(a2>ans)c1->getmax(); if(a1>ans)c0->getmax(); } } }ns[200005],*rt,*ids[200005]; int dx=0; bool operator<(const node&a,const node&b){ if(a.x[dx]!=b.x[dx])return a.x[dx]<b.x[dx]; return a.x[dx^1]<b.x[dx^1]; } int n,q,p; int qo[100005],qx[100005],qy[100005]; node*build(node*l,node*r){ if(l==r)return 0; node*m=l+(r-l>>1); std::nth_element(l,m,r); dx^=1; m->c0=build(l,m); m->c1=build(m+1,r); if(m->c0)m->c0->f=m; if(m->c1)m->c1->f=m; dx^=1; return m; } void ins(node*w){ w->d=1; int x1=w->x[0],x2=w->x[1]; for(;w;w=w->f)w->upd(x1,x2); } int main(){ n=read(); for(int i=0,x,y;i<n;i++){ x=read();y=read(); ns[i].set(x,y,i); } q=read(); p=n; for(int i=0,o,x,y;i<q;i++){ o=read();x=read();y=read(); qo[i]=o;qx[i]=x;qy[i]=y; if(o==0)ns[p++].set(x,y,n+i); } rt=build(ns,ns+p); for(int i=0;i<p;i++)ids[ns[i].id]=ns+i; for(int i=0;i<n;i++)ins(ids[i]); for(int i=0;i<q;i++){ int o=qo[i]; X[0]=qx[i];X[1]=qy[i]; if(o==0)ins(ids[n+i]); else if(o==1){ ans=inf; rt->getmin(); printf("%d ",ans); }else{ ans=-1; rt->getmax(); printf("%d ",ans); } } return 0; }