题目大意:
在一个棋盘上,有N个黑色棋子
每次放到棋盘上一个黑色或白色棋子,如果是白色棋子,他会找出距离(曼哈顿)这个白色棋子最近的黑色棋子
对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离
同一个格子可能有多个棋子
思路:
直接kd tree裸题
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define ll long long 11 #define inf 2139062143 12 #define MAXN 500100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); 19 return x*f; 20 } 21 int n,m,rt,dim,ans; 22 struct node 23 { 24 int d[2],mn[2],mx[2],l,r; 25 node() {d[1]=d[0]=l=r=0;} 26 }tr[MAXN<<1],g; 27 bool operator < (node a,node b) {return a.d[dim]<b.d[dim];} 28 int dis(node a,node b) {return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);} 29 struct kd_tree 30 { 31 void upd(int k) 32 { 33 node l=tr[tr[k].l],r=tr[tr[k].r]; 34 for(int i=0;i<2;i++) 35 { 36 if(tr[k].l) tr[k].mn[i]=min(tr[k].mn[i],l.mn[i]),tr[k].mx[i]=max(tr[k].mx[i],l.mx[i]); 37 if(tr[k].r) tr[k].mn[i]=min(tr[k].mn[i],r.mn[i]),tr[k].mx[i]=max(tr[k].mx[i],r.mx[i]); 38 } 39 } 40 int build(int l,int r,int now) 41 { 42 dim=now; 43 int mid=(l+r)>>1; 44 nth_element(tr+l,tr+mid,tr+r+1); 45 for(int i=0;i<2;i++) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid].d[i]; 46 if(l<mid) tr[mid].l=build(l,mid-1,now^1); 47 if(r>mid) tr[mid].r=build(mid+1,r,now^1); 48 upd(mid); 49 return mid; 50 } 51 int get(int k,node p) 52 { 53 int res=0; 54 for(int i=0;i<2;i++) res+=max(0,tr[k].mn[i]-p.d[i]); 55 for(int i=0;i<2;i++) res+=max(0,p.d[i]-tr[k].mx[i]); 56 return res; 57 } 58 void insert(int k,int now) 59 { 60 if(g.d[now]>=tr[k].d[now]) 61 { 62 if(tr[k].r)insert(tr[k].r,now^1); 63 else 64 { 65 tr[k].r=++n,tr[n]=g; 66 for(int i=0;i<2;i++) tr[n].mn[i]=tr[n].mx[i]=tr[n].d[i]; 67 } 68 } 69 else 70 { 71 if(tr[k].l) insert(tr[k].l,now^1); 72 else 73 { 74 tr[k].l=++n,tr[n]=g; 75 for(int i=0;i<2;i++) tr[n].mn[i]=tr[n].mx[i]=tr[n].d[i]; 76 } 77 } 78 upd(k); 79 } 80 void query(int k,int now) 81 { 82 int d,dl=inf,dr=inf; 83 d=dis(tr[k],g); 84 ans=min(ans,d); 85 if(tr[k].l) dl=get(tr[k].l,g); 86 if(tr[k].r) dr=get(tr[k].r,g); 87 if(dl<dr) 88 { 89 if(dl<ans) query(tr[k].l,now^1); 90 if(dr<ans) query(tr[k].r,now^1); 91 } 92 else 93 { 94 if(dr<ans) query(tr[k].r,now^1); 95 if(dl<ans) query(tr[k].l,now^1); 96 } 97 } 98 }kd; 99 int main() 100 { 101 n=read();m=read(); 102 int x,y,z; 103 for(int i=1;i<=n;i++) tr[i].d[0]=read(),tr[i].d[1]=read(); 104 rt=kd.build(1,n,0); 105 while(m--) 106 { 107 z=read(),x=read(),y=read(); 108 if(z==1) {g.d[0]=x,g.d[1]=y,g.l=g.r=0;kd.insert(rt,0);} 109 else {ans=inf,g.d[0]=x,g.d[1]=y,g.l=g.r=0;kd.query(rt,0);printf("%d ",ans);} 110 } 111 }
今天学会了kd tree 就是一个本质为BST来实现线段树的树