题目链接:BZOJ 2648 SJY摆棋子
题意:
在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
题解:
一个带插入的kd-tree搞之。
1 #include<cstdio> 2 #include<algorithm> 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 6 namespace KD_Tree{ 7 const int N=2e6+7,DI=2,inf=1<<30; 8 struct Node{ 9 int p[DI],f,l,r,mx[DI],mi[DI]; 10 int operator[](const int&idx)const{return p[idx];} 11 void in(int idx,int *v){f=idx;F(i,0,DI-1)p[i]=mi[i]=mx[i]=v[i];} 12 void up(Node&a){ 13 F(i,0,DI-1){ 14 mi[i]=min(mi[i],a.mi[i]); 15 mx[i]=max(mx[i],a.mx[i]); 16 } 17 } 18 }T[N]; 19 int idx[N],cmpd,root,qx,qy,ans; 20 21 bool cmp(const Node&a,const Node&b){ 22 return a[cmpd]!=b[cmpd]?a[cmpd]<b[cmpd]:a[!cmpd]<b[!cmpd]; 23 } 24 void up(int x){ 25 if(T[x].l)T[x].up(T[T[x].l]); 26 if(T[x].r)T[x].up(T[T[x].r]); 27 } 28 int build(int l,int r,int d=0,int f=0) 29 { 30 int mid=l+r>>1; 31 cmpd=d%DI,nth_element(T+l,T+mid,T+r+1,cmp); 32 idx[T[mid].f]=mid,T[mid].f=f; 33 F(i,0,DI-1)T[mid].mi[i]=T[mid].mx[i]=T[mid][i]; 34 T[mid].l=l!=mid?build(l,mid-1,d+1,mid):0; 35 T[mid].r=r!=mid?build(mid+1,r,d+1,mid):0; 36 return up(mid),mid; 37 } 38 int cal(int x){return abs(T[x][0]-qx)+abs(T[x][1]-qy);} 39 int dist(int k){ 40 if(!k)return inf; 41 return max(T[k].mi[0]-qx,0)+max(qx-T[k].mx[0],0)+ 42 max(T[k].mi[1]-qy,0)+max(qy-T[k].mx[1],0); 43 } 44 int Query(int rt=root) 45 { 46 ans=min(ans,cal(rt)); 47 int dl=dist(T[rt].l),dr=dist(T[rt].r); 48 int ls=T[rt].l,rs=T[rt].r; 49 if(dl>dr)swap(ls,rs),swap(dl,dr); 50 if(dl<ans)Query(ls);if(dr<ans)Query(rs); 51 } 52 int query(int x,int y){qx=x,qy=y,ans=inf,Query();return ans;} 53 void insert(int k) 54 { 55 int o=root,d=1,ok=1,*ls,*rs; 56 while(ok) 57 { 58 d^=1,T[o].up(T[k]),ls=&T[o].l,rs=&T[o].r; 59 if(T[k][d]<=T[o][d])*ls?o=*ls:(*ls=k,ok=0); 60 else *rs?o=*rs:(*rs=k,ok=0); 61 } 62 } 63 }; 64 65 int t,n,m,x[2],op; 66 using namespace KD_Tree; 67 68 int main(){ 69 scanf("%d%d",&n,&m); 70 F(i,1,n)scanf("%d%d",x,x+1),T[i].in(i,x); 71 root=build(1,n); 72 F(i,1,m) 73 { 74 scanf("%d%d%d",&op,x,x+1); 75 if(op==1)T[i+n].in(i+n,x),insert(i+n); 76 else printf("%d ",query(x[0],x[1])); 77 } 78 return 0; 79 }