1. 程式人生 > >bzoj2648 SJY擺棋子

bzoj2648 SJY擺棋子

剪枝 fine inline vector des stack kdt element 二分

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

Sample Output

1
2

HINT

kdtree可以過

正解:$kd-tree$。

一個暴力的數據結構——$kd-tree$。。

類似於平面分治,我們按照橫坐標和縱坐標交替二分平面區域。

取當前維坐標的中點,不斷往下遞歸建樹,維護當前點所構成的$kd-tree$的平面區域,即橫坐標和縱坐標的最小最大值。記錄每個點的左兒子和右兒子。

插入結點時,如果到底了就直接新建,否則如果當前維坐標小於根就往左走,否則往右走,類似於$BST$。

查詢的時候直接比較當前點左右子樹的區域到查詢點的距離是否大於$ans$,如果是則直接剪掉,否則就往下搜。註意這裏有一個細微的剪枝,看下代碼吧。我把這個剪枝去掉以後就$T$了。。

總之這就是個亂搞的數據結構,快不快就看你剪枝好不好。

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <cmath>
  9 #include <queue>
 10
#include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (1000010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define fi01() for (RG int i=0;i<=1;++i) 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 int K,n,m,x,y,op,rt,ans; 24 25 struct node{ 26 27 int a[2],mn[2],mx[2],l,r; 28 29 bool operator < (const node &t) const{ 30 return a[K]<t.a[K]; 31 } 32 33 }t[N],S; 34 35 il int gi(){ 36 RG int x=0,q=1; RG char ch=getchar(); 37 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 38 if (ch==-) q=-1,ch=getchar(); 39 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 40 return q*x; 41 } 42 43 il void merge(RG int x){ 44 fi01(){ 45 if (t[x].l){ 46 t[x].mn[i]=min(t[x].mn[i],t[t[x].l].mn[i]); 47 t[x].mx[i]=max(t[x].mx[i],t[t[x].l].mx[i]); 48 } 49 if (t[x].r){ 50 t[x].mn[i]=min(t[x].mn[i],t[t[x].r].mn[i]); 51 t[x].mx[i]=max(t[x].mx[i],t[t[x].r].mx[i]); 52 } 53 } 54 return; 55 } 56 57 il int get(RG int x){ 58 if (!x) return inf; RG int res=0; 59 fi01() res+=max(0,t[x].mn[i]-S.a[i])+max(0,S.a[i]-t[x].mx[i]); 60 return res; 61 } 62 63 il int build(RG int l,RG int r,RG int p){ 64 K=p; RG int mid=(l+r)>>1; nth_element(t+l,t+mid,t+r+1); 65 fi01() t[mid].mn[i]=t[mid].mx[i]=t[mid].a[i]; 66 if (l<mid) t[mid].l=build(l,mid-1,p^1); 67 if (r>mid) t[mid].r=build(mid+1,r,p^1); 68 merge(mid); return mid; 69 } 70 71 il void insert(RG int x,RG int p){ 72 K=p; 73 if (S<t[x]){ 74 if (t[x].l) insert(t[x].l,p^1); else{ 75 t[t[x].l=++n]=S; 76 fi01() t[n].mn[i]=t[n].mx[i]=t[n].a[i]; 77 } 78 } else{ 79 if (t[x].r) insert(t[x].r,p^1); else{ 80 t[t[x].r=++n]=S; 81 fi01() t[n].mn[i]=t[n].mx[i]=t[n].a[i]; 82 } 83 } 84 merge(x); return; 85 } 86 87 il void query(RG int x){ 88 ans=min(ans,abs(S.a[0]-t[x].a[0])+abs(S.a[1]-t[x].a[1])); 89 RG int dl=get(t[x].l),dr=get(t[x].r); 90 if (dl<dr){ 91 if (dl<ans) query(t[x].l); 92 if (dr<ans) query(t[x].r); 93 } else{ 94 if (dr<ans) query(t[x].r); 95 if (dl<ans) query(t[x].l); 96 } 97 return; 98 } 99 100 il void work(){ 101 n=gi(),m=gi(); 102 for (RG int i=1;i<=n;++i) t[i].a[0]=gi(),t[i].a[1]=gi(); 103 rt=build(1,n,0); 104 while (m--){ 105 op=gi(),S.a[0]=gi(),S.a[1]=gi(); 106 S.l=S.r=S.mn[0]=S.mn[1]=S.mx[0]=S.mx[1]=0; 107 if (op==1) insert(rt,0); 108 else ans=inf,query(rt),printf("%d\n",ans); 109 } 110 return; 111 } 112 113 int main(){ 114 File("SJY"); 115 work(); 116 return 0; 117 }

bzoj2648 SJY擺棋子