bzoj 2648: SJY摆棋子

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
 
思路: 涉及到需要插入的kd树。  
  1 #include<bits/stdc++.h>
  2 using namespace std;  
  3 int const maxn=1000000+100; 
  4 int const inf=1e9;    
  5 int n,m,cur,root;   
  6 struct P
  7 {
  8     int d[2],mx[2],mn[2],lch,rch;
  9     int& operator[](int x) {return d[x];}
 10     friend bool operator<(P x,P y) {return x[cur]<y[cur];}
 11     friend int dis(P x,P y) {return abs(x[0] -y[0])+abs(x[1]-y[1]);}
 12 }p[maxn]; 
 13 struct kdtree{
 14   P t[maxn],T;
 15   int ans;
 16   void update(int k){
 17         int l=t[k].lch;  
 18         int r=t[k].rch;   
 19         if(l){
 20             t[k].mn[0]=min(t[k].mn[0],t[l].mn[0]);  
 21             t[k].mx[0]=max(t[k].mx[0],t[l].mx[0]);  
 22             t[k].mn[1]=min(t[k].mn[1],t[l].mn[1]);  
 23             t[k].mx[1]=max(t[k].mx[1],t[l].mx[1]); 
 24         } 
 25         if(r){
 26             t[k].mn[0]=min(t[k].mn[0],t[r].mn[0]); 
 27             t[k].mx[0]=max(t[k].mx[0],t[r].mx[0]);  
 28             t[k].mn[1]=min(t[k].mn[1],t[r].mn[1]);  
 29             t[k].mx[1]=max(t[k].mx[1],t[r].mx[1]);  
 30         }  
 31     } 
 32   int build(int now,int l,int r)
 33   {
 34       cur=now;
 35       int mid=(l+r)/2;
 36       nth_element(p+l,p+mid,p+r+1);
 37       t[mid]=p[mid];
 38       for (int i=0;i<2;i++) t[mid].mn[i]=t[mid].mx[i]=t[mid][i];
 39       if (l<mid) t[mid].lch=build(now^1,l,mid-1);
 40       if (r>mid) t[mid].rch=build(now^1,mid+1,r);
 41       update(mid);
 42       return mid;
 43   }
 44   int getmn(P c){
 45         int ret=0;  
 46         ret+=max(0,c.mn[0]-T[0]);  
 47         ret+=max(0,T[0]-c.mx[0]);
 48         ret+=max(0,c.mn[1]-T[1]);  
 49         ret+=max(0,T[1]-c.mx[1]);  
 50         return ret;  
 51     }   
 52     void querymn(int k){
 53         ans=min(ans,dis(t[k],T)); 
 54         int l=t[k].lch;  
 55         int r=t[k].rch; 
 56         int vl=inf,vr=inf;  
 57         if(l) vl=getmn(t[l]);  
 58         if(r) vr=getmn(t[r]); 
 59         if(vl<vr){
 60             if(vl<ans) querymn(l);  
 61             if(vr<ans) querymn(r);  
 62         }else{
 63             if(vr<ans) querymn(r); 
 64             if(vl<ans) querymn(l); 
 65         } 
 66     }     
 67 
 68     void insert(int k,int now){
 69         if(T[now]>=t[k][now]){
 70             if(t[k].rch) insert(t[k].rch,now^1);  
 71             else {
 72                 t[k].rch=++n;  t[n]=T;  
 73                 //t[n].ch[0]=t[n].ch[1]=0;  
 74                 t[n].mx[0]=t[n].mn[0]=T[0];  
 75                 t[n].mx[1]=t[n].mn[1]=T[1]; 
 76             } 
 77         }else {
 78             if(t[k].lch) insert(t[k].lch,now^1);  
 79             else {
 80                 t[k].lch=++n; t[n]=T;  
 81             //    t[n].ch[0]=t[n].ch[1]=0; 
 82                 t[n].mx[0]=t[n].mn[0]=T[0]; 
 83                 t[n].mx[1]=t[n].mn[1]=T[1];   
 84             } 
 85         }
 86         update(k); 
 87     }     
 88     int query(int x,int y)
 89     {
 90         ans=inf;
 91         T[0]=x;T[1]=y;T.lch=0;T.rch=0;
 92         querymn(root);
 93         return ans;
 94     }
 95     void insert1(int x,int y)
 96     {
 97         T[0]=x;T[1]=y;T.lch=0;T.rch=0;insert(root,0);
 98     }
 99 }kd;    
100 int main(){   
101     scanf("%d%d",&n,&m);  
102     for(int i=1;i<=n;i++){
103         scanf("%d%d",&p[i][0],&p[i][1]);    
104     }  
105     root=kd.build(0,1,n); 
106     while (m--){
107         int t,x,y;  
108         scanf("%d%d%d",&t,&x,&y);  
109         if(t==1) kd.insert1(x,y);  
110         else printf("%d\n",kd.query(x,y)); 
111     } 
112     return 0; 
113 } 
View Code

 

posted @ 2019-07-04 10:56  zjxxcn  阅读(152)  评论(0编辑  收藏  举报