• 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
    ",query(x[0],x[1]));
    77     }
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    [转载]选择比努力更重要
    [转载]weblogic中文文档——domain_config
    Java API 帮助文档中英文版下载
    [转载]BAT文件语法和技巧
    搜索字符串并高亮显示
    [转载]配置WebLogic Server集群
    Linux目录架构
    多文档多视图之间的切换过程和当文档多视图之间的切换过程
    SendMessage及WPRAME、LPARAME
    下MFC中对象、句柄、ID之间的区别.
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7301458.html
Copyright © 2020-2023  润新知