【BZOJ】【2648】SJY摆棋子&【BZOJ】【2716】【Violet 3】天使玩偶
KD-Tree
传说中的kd树。。。前去膜拜了一下……写道模板题>_<
写kdtree的一些感想:
插入的时候是像可持久化线段树一样直接在最后开新节点,然后更新它所在的块。。
然而其实也是用原来的叶子再分割一次这块区域?
1 /************************************************************** 2 Problem: 2716 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:16492 ms 7 Memory:26280 kb 8 ****************************************************************/ 9 10 //BZOJ 2716 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=800010,INF=1e9; 29 /*******************template********************/ 30 31 struct node{ 32 int d[2],mn[2],mx[2],l,r; 33 int& operator [] (int x){return d[x];} 34 void read(){d[0]=getint(); d[1]=getint();} 35 }t[N],tmp; 36 int n,m,D,root,ans,cnt; 37 38 inline int dis(node a,node b){return abs(a[0]-b[0])+abs(a[1]-b[1]);} 39 bool operator < (node a,node b){return a[D]<b[D] || (a[D]==b[D] && a[!D]<b[!D]);} 40 41 42 #define L t[o].l 43 #define R t[o].r 44 #define mid (l+r>>1) 45 void Push_up(int o){ 46 F(i,0,1){ 47 if (L){ t[o].mn[i]=min(t[o].mn[i],t[L].mn[i]); t[o].mx[i]=max(t[o].mx[i],t[L].mx[i]);} 48 if (R){ t[o].mn[i]=min(t[o].mn[i],t[R].mn[i]); t[o].mx[i]=max(t[o].mx[i],t[R].mx[i]);} 49 } 50 } 51 52 int build(int l,int r,int dir){ 53 D=dir; 54 nth_element(t+l,t+mid,t+r+1); 55 F(i,0,1) t[mid].mn[i]=t[mid].mx[i]=t[mid][i]; 56 if (l<mid) t[mid].l=build(l,mid-1,dir^1); 57 if (r>mid) t[mid].r=build(mid+1,r,dir^1); 58 Push_up(mid); 59 return mid; 60 } 61 62 inline void Insert(int &o,int dir){ 63 if (!o){ 64 o=++cnt; t[o]=tmp; 65 F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i]; 66 return; 67 } 68 if (tmp[dir]<t[o][dir]) Insert(L,dir^1); 69 else Insert(R,dir^1); 70 Push_up(o); 71 } 72 73 inline int getdis(int o){ 74 if (!o) return INF; 75 int ans=0; 76 F(i,0,1) ans+=max(0,t[o].mn[i]-tmp[i]); 77 F(i,0,1) ans+=max(0,tmp[i]-t[o].mx[i]); 78 return ans; 79 } 80 81 inline void query(int o){ 82 int dl=getdis(L),dr=getdis(R),d0=dis(t[o],tmp); 83 ans=min(ans,d0); 84 if (dl<dr){ 85 if (dl<ans) query(L); 86 if (dr<ans) query(R); 87 }else{ 88 if (dr<ans) query(R); 89 if (dl<ans) query(L); 90 } 91 } 92 93 int main(){ 94 #ifndef ONLINE_JUDGE 95 freopen("2716.in","r",stdin); 96 freopen("2716.out","w",stdout); 97 #endif 98 cnt=n=getint(); m=getint(); 99 F(i,1,n) t[i].read(); 100 root=build(1,n,1); 101 F(i,1,m){ 102 int t=getint(); tmp.read(); 103 if (t==1) Insert(root,1); 104 else{ 105 ans=INF; 106 query(root); 107 printf("%d\n",ans); 108 } 109 } 110 return 0; 111 }
2648: SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1090 Solved: 359
[Submit][Status][Discuss]
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
HINT
kdtree可以过