zoukankan      html  css  js  c++  java
  • BZOJ2648 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-tree

    解题报告:

      大概题意是在一个棋盘上初始有一些黑棋子,接着要放一些黑白棋子,若放的是白棋子则回答离它最近的(曼哈顿距离)黑棋子的距离

      参考了大神的博客:http://blog.sina.com.cn/s/blog_8d5d2f040101888r.html & http://blog.csdn.net/jiangshibiao/article/details/34144829

     

      做这道题其实只是为了学kd-tree,据说是模板题,果然轻松AC了  

      先花了一个晚上学了kd-tree,然后就对着纸模拟了一下感觉会了,于是就顺手切掉了这道模板题。

      大致思想感觉我看的那篇博客里面讲得比较清楚了,还是大概说一下吧。

      这道题需要维护一个二维空间上的很多个点,然后查询离新加入的白点最近的黑点(曼哈顿距离)的距离,当然也可以直接加入一些黑点。

      kd-tree有点像分治,也有点像线段树。

      每次二分区间内点的横坐标或者纵坐标,然后以mid为界,两边分别处理。每个结点维护四个方向上的控制范围内的最值,画个图yy一下,所以保存四个值:控制范围内纵坐标的最大最小值,横坐标的最大最小值。再存一下这个点本身的横纵坐标。mid可以理解成这个区间的首领。 

      为了维护上述操作,我们需要用到nth_element这个STL,作用的话可以百度一下。

      接着递归往下建就可以了,注意存一下每个结点控制区间下的子区间的控制节点(可以理解成子区间内的两个首领)。

      所以我们可以轻松的build出kd-tree。

      然后是插入,就是不断与当前结点的x,y按照现在的D(按横坐标还是纵坐标为第一关键字排序)比较之后决定往左还是往右插入,发现空位插进去就可以了。

      查询的话有一些小技巧,我理解成是估算一下预计ans然后看先处理左边还是右边,往下更新就可以了。具体的看代码。

     

      1 //It is made by jump~
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #ifdef WIN32   
     13 #define OT "%I64d"
     14 #else
     15 #define OT "%lld"
     16 #endif
     17 using namespace std;
     18 typedef long long LL;
     19 const int MAXN = 1000011;
     20 const int inf = (1<<30);
     21 int n,m;
     22 int nowD;
     23 int root;
     24 int ans;
     25 int ql,qr;
     26 
     27 struct node{
     28     int Min[2],Max[2];
     29     int d[2];
     30     int l,r;
     31 }t[MAXN*2];
     32 
     33 inline int getint()
     34 {
     35        int w=0,q=0;
     36        char c=getchar();
     37        while((c<'0' || c>'9') && c!='-') c=getchar();
     38        if (c=='-')  q=1, c=getchar();
     39        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     40        return q ? -w : w;
     41 }
     42 
     43 inline bool cmp(node q,node qq){ 
     44     if(q.d[nowD]==qq.d[nowD]) return q.d[!nowD]<qq.d[!nowD]; 
     45     return q.d[nowD]<qq.d[nowD];
     46 }
     47 
     48 inline void kd_updata(int now){
     49     if(t[now].l) {
     50     if(t[t[now].l].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].l].Max[0];
     51     if(t[t[now].l].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].l].Max[1];
     52     if(t[t[now].l].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].l].Min[0];
     53     if(t[t[now].l].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].l].Min[1];
     54     }
     55     if(t[now].r) {
     56     if(t[t[now].r].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].r].Max[0];
     57     if(t[t[now].r].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].r].Max[1];
     58     if(t[t[now].r].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].r].Min[0];
     59     if(t[t[now].r].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].r].Min[1];
     60     }
     61 }
     62 
     63 inline int kd_build(int l,int r,int D){
     64     int mid=(l+r)/2;
     65     nowD=D;
     66     nth_element(t+l+1,t+mid+1,t+r+1,cmp);
     67 
     68     if(l!=mid) t[mid].l=kd_build(l,mid-1,!D);
     69     if(r!=mid) t[mid].r=kd_build(mid+1,r,!D);
     70     t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
     71     t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
     72     kd_updata(mid);
     73     return mid;
     74 }
     75 
     76 inline int dist(int p){
     77     int dis=0;
     78     if(ql<t[p].Min[0]) dis+=t[p].Min[0]-ql;
     79     if(ql>t[p].Max[0]) dis+=ql-t[p].Max[0];
     80     if(qr<t[p].Min[1]) dis+=t[p].Min[1]-qr;
     81     if(qr>t[p].Max[1]) dis+=qr-t[p].Max[1];
     82     return dis;
     83 }
     84 
     85 inline void kd_query(int p){
     86     int dl,dr,d0;
     87     d0=abs(t[p].d[0]-ql)+abs(t[p].d[1]-qr);
     88     if(d0<ans) ans=d0;
     89     if(t[p].l) dl=dist(t[p].l); else dl=inf;
     90     if(t[p].r) dr=dist(t[p].r); else dr=inf;
     91 
     92     if(dl<dr) {
     93     if(dl<ans) kd_query(t[p].l);
     94     if(dr<ans) kd_query(t[p].r);
     95     }
     96     else{
     97     if(dr<ans) kd_query(t[p].r);
     98     if(dl<ans) kd_query(t[p].l);
     99     }
    100 }
    101 
    102 inline void kd_insert(int now){
    103     int p=root,D=0;
    104     while(true){
    105     if(t[now].Max[0]>t[p].Max[0]) t[p].Max[0]=t[now].Max[0];
    106     if(t[now].Max[1]>t[p].Max[1]) t[p].Max[1]=t[now].Max[1];
    107     if(t[now].Min[0]<t[p].Min[0]) t[p].Min[0]=t[now].Min[0];
    108     if(t[now].Min[1]<t[p].Min[1]) t[p].Min[1]=t[now].Min[1];
    109 
    110     if(t[now].d[D]>=t[p].d[D]) {
    111         if(!t[p].r){
    112         t[p].r=now;
    113         return;
    114         }
    115         else p=t[p].r;
    116     }
    117     else{
    118         if(!t[p].l) {
    119         t[p].l=now;
    120         return ;
    121         }
    122         else p=t[p].l;
    123     }
    124 
    125     D=!D;
    126     }
    127 }
    128 
    129 int main()
    130 {
    131   n=getint();m=getint();
    132   for(int i=1;i<=n;i++) t[i].d[0]=getint(),t[i].d[1]=getint();
    133   root=kd_build(1,n,0);
    134 
    135   int x,y,z;
    136   for(int i=1;i<=m;i++) {
    137       x=getint(); y=getint(); z=getint();
    138       if(x==1) {
    139       n++;
    140       t[n].Max[0]=t[n].Min[0]=t[n].d[0]=y; t[n].Max[1]=t[n].Min[1]=t[n].d[1]=z;
    141       kd_insert(n);
    142       }
    143       else{
    144       ans=inf;
    145       ql=y,qr=z;
    146       kd_query(root);
    147       printf("%d
    ",ans);
    148       }
    149   }
    150   return 0;
    151 }
  • 相关阅读:
    操作系统的磁盘结构、磁盘管理、磁盘调度算法
    ArrayList源码解析--值得深读
    深入理解static、volatile关键字
    7:高阶张量操作
    6:统计属性
    5:张量的基本运算
    4.1张量的操作(broadcasting维度自动扩张,拼接与拆分)
    4:张量操作
    3:索引与切片
    2:pytorch的基本数据类型以及张量的创建
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5513620.html
Copyright © 2011-2022 走看看