bzoj 2648: SJY摆棋子
Description
这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
Input
第一行两个数 N M
以后M行,每行3个数 t x y
如果t=1 那么放下一个黑色棋子
如果t=2 那么放下一个白色棋子
Output
对于每个T=2 输出一个最小距离
Sample Input
2 3
1 1
2 3
2 1 2
1 3 3
2 4 2
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
思路: 涉及到需要插入的kd树。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const maxn=1000000+100; 4 int const inf=1e9; 5 int n,m,cur,root; 6 struct P 7 { 8 int d[2],mx[2],mn[2],lch,rch; 9 int& operator[](int x) {return d[x];} 10 friend bool operator<(P x,P y) {return x[cur]<y[cur];} 11 friend int dis(P x,P y) {return abs(x[0] -y[0])+abs(x[1]-y[1]);} 12 }p[maxn]; 13 struct kdtree{ 14 P t[maxn],T; 15 int ans; 16 void update(int k){ 17 int l=t[k].lch; 18 int r=t[k].rch; 19 if(l){ 20 t[k].mn[0]=min(t[k].mn[0],t[l].mn[0]); 21 t[k].mx[0]=max(t[k].mx[0],t[l].mx[0]); 22 t[k].mn[1]=min(t[k].mn[1],t[l].mn[1]); 23 t[k].mx[1]=max(t[k].mx[1],t[l].mx[1]); 24 } 25 if(r){ 26 t[k].mn[0]=min(t[k].mn[0],t[r].mn[0]); 27 t[k].mx[0]=max(t[k].mx[0],t[r].mx[0]); 28 t[k].mn[1]=min(t[k].mn[1],t[r].mn[1]); 29 t[k].mx[1]=max(t[k].mx[1],t[r].mx[1]); 30 } 31 } 32 int build(int now,int l,int r) 33 { 34 cur=now; 35 int mid=(l+r)/2; 36 nth_element(p+l,p+mid,p+r+1); 37 t[mid]=p[mid]; 38 for (int i=0;i<2;i++) t[mid].mn[i]=t[mid].mx[i]=t[mid][i]; 39 if (l<mid) t[mid].lch=build(now^1,l,mid-1); 40 if (r>mid) t[mid].rch=build(now^1,mid+1,r); 41 update(mid); 42 return mid; 43 } 44 int getmn(P c){ 45 int ret=0; 46 ret+=max(0,c.mn[0]-T[0]); 47 ret+=max(0,T[0]-c.mx[0]); 48 ret+=max(0,c.mn[1]-T[1]); 49 ret+=max(0,T[1]-c.mx[1]); 50 return ret; 51 } 52 void querymn(int k){ 53 ans=min(ans,dis(t[k],T)); 54 int l=t[k].lch; 55 int r=t[k].rch; 56 int vl=inf,vr=inf; 57 if(l) vl=getmn(t[l]); 58 if(r) vr=getmn(t[r]); 59 if(vl<vr){ 60 if(vl<ans) querymn(l); 61 if(vr<ans) querymn(r); 62 }else{ 63 if(vr<ans) querymn(r); 64 if(vl<ans) querymn(l); 65 } 66 } 67 68 void insert(int k,int now){ 69 if(T[now]>=t[k][now]){ 70 if(t[k].rch) insert(t[k].rch,now^1); 71 else { 72 t[k].rch=++n; t[n]=T; 73 //t[n].ch[0]=t[n].ch[1]=0; 74 t[n].mx[0]=t[n].mn[0]=T[0]; 75 t[n].mx[1]=t[n].mn[1]=T[1]; 76 } 77 }else { 78 if(t[k].lch) insert(t[k].lch,now^1); 79 else { 80 t[k].lch=++n; t[n]=T; 81 // t[n].ch[0]=t[n].ch[1]=0; 82 t[n].mx[0]=t[n].mn[0]=T[0]; 83 t[n].mx[1]=t[n].mn[1]=T[1]; 84 } 85 } 86 update(k); 87 } 88 int query(int x,int y) 89 { 90 ans=inf; 91 T[0]=x;T[1]=y;T.lch=0;T.rch=0; 92 querymn(root); 93 return ans; 94 } 95 void insert1(int x,int y) 96 { 97 T[0]=x;T[1]=y;T.lch=0;T.rch=0;insert(root,0); 98 } 99 }kd; 100 int main(){ 101 scanf("%d%d",&n,&m); 102 for(int i=1;i<=n;i++){ 103 scanf("%d%d",&p[i][0],&p[i][1]); 104 } 105 root=kd.build(0,1,n); 106 while (m--){ 107 int t,x,y; 108 scanf("%d%d%d",&t,&x,&y); 109 if(t==1) kd.insert1(x,y); 110 else printf("%d\n",kd.query(x,y)); 111 } 112 return 0; 113 }