BZOJ 2648 SJY摆棋子(KD-Tree)

题目链接:BZOJ 2648  SJY摆棋子

题意:

在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。

题解:

一个带插入的kd-tree搞之。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 
 6 namespace KD_Tree{
 7     const int N=2e6+7,DI=2,inf=1<<30;
 8     struct Node{
 9         int p[DI],f,l,r,mx[DI],mi[DI];
10         int operator[](const int&idx)const{return p[idx];}
11         void in(int idx,int *v){f=idx;F(i,0,DI-1)p[i]=mi[i]=mx[i]=v[i];}
12         void up(Node&a){
13             F(i,0,DI-1){
14                 mi[i]=min(mi[i],a.mi[i]);
15                 mx[i]=max(mx[i],a.mx[i]);
16             }
17         }
18     }T[N];
19     int idx[N],cmpd,root,qx,qy,ans;
20     
21     bool cmp(const Node&a,const Node&b){
22         return a[cmpd]!=b[cmpd]?a[cmpd]<b[cmpd]:a[!cmpd]<b[!cmpd];
23     }
24     void up(int x){
25         if(T[x].l)T[x].up(T[T[x].l]);
26         if(T[x].r)T[x].up(T[T[x].r]);
27     }
28     int build(int l,int r,int d=0,int f=0)
29     {
30         int mid=l+r>>1;
31         cmpd=d%DI,nth_element(T+l,T+mid,T+r+1,cmp);
32         idx[T[mid].f]=mid,T[mid].f=f;
33         F(i,0,DI-1)T[mid].mi[i]=T[mid].mx[i]=T[mid][i];
34         T[mid].l=l!=mid?build(l,mid-1,d+1,mid):0;
35         T[mid].r=r!=mid?build(mid+1,r,d+1,mid):0;
36         return up(mid),mid;
37     }
38     int cal(int x){return abs(T[x][0]-qx)+abs(T[x][1]-qy);}
39     int dist(int k){
40         if(!k)return inf;
41         return max(T[k].mi[0]-qx,0)+max(qx-T[k].mx[0],0)+
42         max(T[k].mi[1]-qy,0)+max(qy-T[k].mx[1],0);
43     }
44     int Query(int rt=root)
45     {
46         ans=min(ans,cal(rt));
47         int dl=dist(T[rt].l),dr=dist(T[rt].r);
48         int ls=T[rt].l,rs=T[rt].r;
49         if(dl>dr)swap(ls,rs),swap(dl,dr);
50         if(dl<ans)Query(ls);if(dr<ans)Query(rs);
51     }
52     int query(int x,int y){qx=x,qy=y,ans=inf,Query();return ans;}
53     void insert(int k)
54     {
55         int o=root,d=1,ok=1,*ls,*rs;
56         while(ok)
57         {
58             d^=1,T[o].up(T[k]),ls=&T[o].l,rs=&T[o].r;
59             if(T[k][d]<=T[o][d])*ls?o=*ls:(*ls=k,ok=0);
60             else *rs?o=*rs:(*rs=k,ok=0);
61         }
62     }
63 };
64 
65 int t,n,m,x[2],op;
66 using namespace KD_Tree;
67 
68 int main(){
69     scanf("%d%d",&n,&m);
70     F(i,1,n)scanf("%d%d",x,x+1),T[i].in(i,x);
71     root=build(1,n);
72     F(i,1,m)
73     {
74         scanf("%d%d%d",&op,x,x+1);
75         if(op==1)T[i+n].in(i+n,x),insert(i+n);
76         else printf("%d\n",query(x[0],x[1]));
77     }
78     return 0;
79 }
View Code

 

posted @ 2017-08-07 21:36  bin_gege  阅读(118)  评论(0编辑  收藏  举报