【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 }
View Code

2648: SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output


1
2

HINT

 

kdtree可以过

Source

[Submit][Status][Discuss]
posted @ 2015-05-19 11:49  Tunix  阅读(297)  评论(0编辑  收藏  举报