BZOJ2648/2716:SJY摆棋子/[Violet]天使玩偶(K-D Tree)
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
Solution
K-D Tree模板题,注意不替罪羊重构的话会TLE
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #define N (1000000+1000) 7 #define INF 0x7fffffff 8 using namespace std; 9 10 int n,m,D,ans,opt,x,y,Root; 11 double alpha=0.75; 12 13 struct Node 14 { 15 int d[2],Max[2],Min[2],lson,rson,size; 16 bool operator < (const Node &a) const {return d[D]<a.d[D];} 17 Node (int x=0,int y=0) 18 { 19 lson=rson=0; d[0]=x; d[1]=y;; 20 Max[0]=Min[0]=d[0]; 21 Max[1]=Min[1]=d[1]; 22 } 23 }p[N],T; 24 25 int stack[N],cnt,top; 26 int NewNode() 27 { 28 if (top) return stack[top--]; 29 return ++cnt; 30 } 31 32 struct KDT 33 { 34 Node Tree[N]; 35 36 void Update(int now) 37 { 38 int ls=Tree[now].lson,rs=Tree[now].rson; 39 for (int i=0; i<=1; ++i) 40 { 41 Tree[now].Max[i]=Tree[now].Min[i]=Tree[now].d[i]; 42 if (ls) 43 { 44 Tree[now].Max[i]=max(Tree[now].Max[i],Tree[ls].Max[i]); 45 Tree[now].Min[i]=min(Tree[now].Min[i],Tree[ls].Min[i]); 46 } 47 if (rs) 48 { 49 Tree[now].Max[i]=max(Tree[now].Max[i],Tree[rs].Max[i]); 50 Tree[now].Min[i]=min(Tree[now].Min[i],Tree[rs].Min[i]); 51 } 52 } 53 Tree[now].size=Tree[ls].size+Tree[rs].size+1; 54 } 55 int Build(int opt,int l,int r) 56 { 57 if (l>r) return 0; 58 int mid=(l+r)>>1,now=NewNode(); 59 D=opt; nth_element(p+l,p+mid,p+r+1); 60 Tree[now]=p[mid]; Tree[now].size=1; 61 Tree[now].lson=Build(opt^1,l,mid-1); 62 Tree[now].rson=Build(opt^1,mid+1,r); 63 Update(now); 64 return now; 65 } 66 int Get_min(int now) 67 { 68 int ans=0; 69 for (int i=0; i<=1; ++i) 70 { 71 ans+=max(0,T.d[i]-Tree[now].Max[i]); 72 ans+=max(0,Tree[now].Min[i]-T.d[i]); 73 } 74 return ans; 75 } 76 void Query(int now) 77 { 78 ans=min(ans,abs(T.d[0]-Tree[now].d[0])+abs(T.d[1]-Tree[now].d[1])); 79 int ls=Tree[now].lson,rs=Tree[now].rson,lans=INF,rans=INF; 80 if (ls) lans=Get_min(ls); 81 if (rs) rans=Get_min(rs); 82 if (lans<rans) 83 { 84 if (lans<ans) Query(ls); 85 if (rans<ans) Query(rs); 86 } 87 else 88 { 89 if (rans<ans) Query(rs); 90 if (lans<ans) Query(ls); 91 } 92 } 93 void Dfs(int now,int sz) 94 { 95 int ls=Tree[now].lson,rs=Tree[now].rson; 96 if (ls) Dfs(ls,sz); 97 p[sz+Tree[ls].size]=Tree[now]; 98 stack[++top]=now; 99 if (rs) Dfs(rs,sz+Tree[ls].size+1); 100 } 101 void Check(int &now,int opt) 102 { 103 int ls=Tree[now].lson, rs=Tree[now].rson; 104 if (Tree[ls].size>alpha*Tree[now].size || Tree[rs].size>alpha*Tree[now].size) 105 { 106 Dfs(now,1); 107 now=Build(opt,1,Tree[now].size); 108 } 109 } 110 void Insert(int &now,int x,int opt) 111 { 112 if (Tree[x].d[opt]<=Tree[now].d[opt]) 113 { 114 if (Tree[now].lson) Insert(Tree[now].lson,x,opt^1); 115 else Tree[now].lson=x; 116 } 117 else 118 { 119 if (Tree[now].rson) Insert(Tree[now].rson,x,opt^1); 120 else Tree[now].rson=x; 121 } 122 Update(now); Check(now,opt); 123 } 124 }KDT; 125 126 int main() 127 { 128 scanf("%d%d",&n,&m); 129 for (int i=1; i<=n; ++i) 130 { 131 scanf("%d%d",&x,&y); 132 p[i].d[0]=x; p[i].d[1]=y; 133 } 134 Root=KDT.Build(0,1,n); 135 for (int i=1; i<=m; ++i) 136 { 137 scanf("%d%d%d",&opt,&x,&y); 138 if (opt==1) 139 { 140 int t=NewNode(); 141 KDT.Tree[t]=Node(x,y); 142 KDT.Tree[t].size=1; 143 KDT.Insert(Root,t,0); 144 } 145 else 146 { 147 T.d[0]=x; T.d[1]=y; ans=INF; 148 KDT.Query(Root); 149 printf("%d\n",ans); 150 } 151 } 152 }