• bzoj 2648 SJY摆棋子


    题目大意:

    在一个棋盘上,有N个黑色棋子

    每次放到棋盘上一个黑色或白色棋子,如果是白色棋子,他会找出距离(曼哈顿)这个白色棋子最近的黑色棋子

    对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离

    同一个格子可能有多个棋子

    思路:

    直接kd tree裸题

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 #include<map>
     10 #define ll long long
     11 #define inf 2139062143
     12 #define MAXN 500100
     13 using namespace std;
     14 inline int read()
     15 {
     16     int x=0,f=1;char ch=getchar();
     17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
     18     while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
     19     return x*f;
     20 }
     21 int n,m,rt,dim,ans;
     22 struct node
     23 {
     24     int d[2],mn[2],mx[2],l,r;
     25     node() {d[1]=d[0]=l=r=0;}
     26 }tr[MAXN<<1],g;
     27 bool operator < (node a,node b) {return a.d[dim]<b.d[dim];}
     28 int dis(node a,node b) {return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);}
     29 struct kd_tree
     30 {
     31     void upd(int k)
     32     {
     33         node l=tr[tr[k].l],r=tr[tr[k].r];
     34         for(int i=0;i<2;i++)
     35         {
     36             if(tr[k].l) tr[k].mn[i]=min(tr[k].mn[i],l.mn[i]),tr[k].mx[i]=max(tr[k].mx[i],l.mx[i]);
     37             if(tr[k].r) tr[k].mn[i]=min(tr[k].mn[i],r.mn[i]),tr[k].mx[i]=max(tr[k].mx[i],r.mx[i]);
     38         }
     39     }
     40     int build(int l,int r,int now)
     41     {
     42         dim=now;
     43         int mid=(l+r)>>1;
     44         nth_element(tr+l,tr+mid,tr+r+1);
     45         for(int i=0;i<2;i++) tr[mid].mn[i]=tr[mid].mx[i]=tr[mid].d[i];
     46         if(l<mid) tr[mid].l=build(l,mid-1,now^1);
     47         if(r>mid) tr[mid].r=build(mid+1,r,now^1);
     48         upd(mid);
     49         return mid;
     50     }
     51     int get(int k,node p)
     52     {
     53         int res=0;
     54         for(int i=0;i<2;i++) res+=max(0,tr[k].mn[i]-p.d[i]);
     55         for(int i=0;i<2;i++) res+=max(0,p.d[i]-tr[k].mx[i]);
     56         return res;
     57     }
     58     void insert(int k,int now)
     59     {
     60         if(g.d[now]>=tr[k].d[now])
     61         {
     62             if(tr[k].r)insert(tr[k].r,now^1);
     63             else 
     64             {
     65                 tr[k].r=++n,tr[n]=g;
     66                 for(int i=0;i<2;i++) tr[n].mn[i]=tr[n].mx[i]=tr[n].d[i];
     67             }
     68         }
     69         else 
     70         {
     71             if(tr[k].l) insert(tr[k].l,now^1);
     72             else 
     73             {
     74                 tr[k].l=++n,tr[n]=g;
     75                 for(int i=0;i<2;i++) tr[n].mn[i]=tr[n].mx[i]=tr[n].d[i];
     76             }
     77         }
     78         upd(k);
     79     }
     80     void query(int k,int now)
     81     {
     82         int d,dl=inf,dr=inf;
     83         d=dis(tr[k],g);
     84         ans=min(ans,d);
     85         if(tr[k].l) dl=get(tr[k].l,g);
     86         if(tr[k].r) dr=get(tr[k].r,g);
     87         if(dl<dr)
     88         {
     89             if(dl<ans) query(tr[k].l,now^1);
     90             if(dr<ans) query(tr[k].r,now^1);
     91         }
     92         else
     93         {
     94             if(dr<ans) query(tr[k].r,now^1);
     95             if(dl<ans) query(tr[k].l,now^1);
     96         }
     97     }
     98 }kd;
     99 int main()
    100 {
    101     n=read();m=read();
    102     int x,y,z;
    103     for(int i=1;i<=n;i++) tr[i].d[0]=read(),tr[i].d[1]=read();
    104     rt=kd.build(1,n,0);
    105     while(m--)
    106     {
    107         z=read(),x=read(),y=read();
    108         if(z==1) {g.d[0]=x,g.d[1]=y,g.l=g.r=0;kd.insert(rt,0);}
    109         else {ans=inf,g.d[0]=x,g.d[1]=y,g.l=g.r=0;kd.query(rt,0);printf("%d
    ",ans);}
    110     }
    111 }
    View Code

    今天学会了kd tree 就是一个本质为BST来实现线段树的树

  • 相关阅读:
    跟我学SharePoint 2013视频培训课程——什么是SharePoint 2013(1)
    SharePoint 关于拓扑错误的解决方案
    SharePoint 2010、2013多个域之间互信(Domain Trust)的设计与实施
    SharePoint 2013 Disaster Recovery——迁移内容数据库
    windows-根据进程PID 获取进程路径
    kernel 获取ntoskrnl.exe基址
    ring3 x32挂起进程注入原理.
    CryEntryBuffer
    windows内核代码之进程操作
    驱动中遍历模块,以及获取ntoskrnl.exe基址
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8421247.html
Copyright © 2020-2023  润新知