zoukankan      html  css  js  c++  java
  • BZOJ1941 [Sdoi2010]Hide and Seek

    Description

    小 猪iPig在PKU刚上完了无聊的猪性代数课,天资聪慧的iPig被这门对他来说无比简单的课弄得非常寂寞,为了消除寂寞感,他决定和他的好朋友 giPi(鸡皮)玩一个更加寂寞的游戏---捉迷藏。 但是,他们觉得,玩普通的捉迷藏没什么意思,还是不够寂寞,于是,他们决定玩寂寞无比的螃蟹版捉迷藏,顾名思义,就是说他们在玩游戏的时候只能沿水平或垂 直方向走。一番寂寞的剪刀石头布后,他们决定iPig去捉giPi。由于他们都很熟悉PKU的地形了,所以giPi只会躲在PKU内n个隐秘地点,显然 iPig也只会在那n个地点内找giPi。游戏一开始,他们选定一个地点,iPig保持不动,然后giPi用30秒的时间逃离现场(显然,giPi不会呆 在原地)。然后iPig会随机地去找giPi,直到找到为止。由于iPig很懒,所以他到总是走最短的路径,而且,他选择起始点不是随便选的,他想找一个 地点,使得该地点到最远的地点和最近的地点的距离差最小。iPig现在想知道这个距离差最小是多少。 由于iPig现在手上没有电脑,所以不能编程解决这个如此简单的问题,所以他马上打了个电话,要求你帮他解决这个问题。iPig告诉了你PKU的n个隐秘 地点的坐标,请你编程求出iPig的问题。

    Input

    第一行输入一个整数N 第2~N+1行,每行两个整数X,Y,表示第i个地点的坐标

    Output

    一个整数,为距离差的最小值。

    Sample Input

    4
    0 0
    1 0
    0 1
    1 1

    Sample Output

    1

    HINT

    对于30%的数据,N<=1000 对于100%的数据,N<=500000,0<=X,Y<=10^8 保证数据没有重点保证N>=2

    Source

     
     
    正解:kd-tree
    解题报告:
      看完之后,妈呀这不是裸题吗???直接蒯了BZOJ2648的模板,然后加了个对于最大距离的查询。
      注意一下因为最近距离不能为0,所以需要特判一下ans!=0,每次查询一下最大距离、最小距离,相减即可。另外,我在重写查找最大距离的函数的时候直接蒯了最小距离的求法,结果萎了,我真傻真的。
       
     
      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,nowD,root,ans,ql,qr,ans2;
     22 int zong;
     23 struct node{
     24     int Min[2],Max[2];//控制范围内的极值
     25     int d[2];//结点本身
     26     int l,r;//控制的左范围和右范围
     27 }t[MAXN*2];
     28 
     29 inline int getint()
     30 {
     31        int w=0,q=0;
     32        char c=getchar();
     33        while((c<'0' || c>'9') && c!='-') c=getchar();
     34        if (c=='-')  q=1, c=getchar();
     35        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
     36        return q ? -w : w;
     37 }
     38 
     39 inline bool cmp(node q,node qq){ 
     40     if(q.d[nowD]==qq.d[nowD]) return q.d[!nowD]<qq.d[!nowD]; 
     41     return q.d[nowD]<qq.d[nowD];
     42 }
     43 
     44 inline void kd_updata(int now){
     45     if(t[now].l) {
     46     if(t[t[now].l].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].l].Max[0];
     47     if(t[t[now].l].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].l].Max[1];
     48     if(t[t[now].l].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].l].Min[0];
     49     if(t[t[now].l].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].l].Min[1];
     50     }
     51     if(t[now].r) {
     52     if(t[t[now].r].Max[0]>t[now].Max[0]) t[now].Max[0]=t[t[now].r].Max[0];
     53     if(t[t[now].r].Max[1]>t[now].Max[1]) t[now].Max[1]=t[t[now].r].Max[1];
     54     if(t[t[now].r].Min[0]<t[now].Min[0]) t[now].Min[0]=t[t[now].r].Min[0];
     55     if(t[t[now].r].Min[1]<t[now].Min[1]) t[now].Min[1]=t[t[now].r].Min[1];
     56     }
     57 }
     58 
     59 inline int kd_build(int l,int r,int D){
     60     int mid=(l+r)/2;
     61     nowD=D;
     62     nth_element(t+l+1,t+mid+1,t+r+1,cmp);
     63 
     64     if(l!=mid) t[mid].l=kd_build(l,mid-1,!D);
     65     if(r!=mid) t[mid].r=kd_build(mid+1,r,!D);
     66     t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
     67     t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
     68     kd_updata(mid);
     69     return mid;
     70 }
     71 
     72 inline int dist(int p){
     73     int dis=0;    
     74     if(ql<t[p].Min[0]) dis+=t[p].Min[0]-ql;
     75     if(ql>t[p].Max[0]) dis+=ql-t[p].Max[0];
     76     if(qr<t[p].Min[1]) dis+=t[p].Min[1]-qr;
     77     if(qr>t[p].Max[1]) dis+=qr-t[p].Max[1];
     78     return dis;
     79 }
     80 
     81 inline void kd_query_min(int p){
     82     int dl,dr,d0;
     83     d0=abs(t[p].d[0]-ql)+abs(t[p].d[1]-qr);
     84     if(d0<ans && d0!=0) ans=d0;//一直深入到答案最小的结点才会更新最终答案
     85 
     86     if(t[p].l) dl=dist(t[p].l); else dl=inf;
     87     if(t[p].r) dr=dist(t[p].r); else dr=inf;
     88 
     89     if(dl<dr) {
     90     if(dl<ans) kd_query_min(t[p].l);
     91     if(dr<ans) kd_query_min(t[p].r);
     92     }
     93     else{
     94     if(dr<ans) kd_query_min(t[p].r);
     95     if(dl<ans) kd_query_min(t[p].l);
     96     }
     97 }
     98 
     99 inline int dis_max(int p){
    100     int dis=0;
    101     dis+=max(abs(t[p].Min[0]-ql),abs(ql-t[p].Max[0]));
    102     dis+=max(abs(t[p].Min[1]-qr),abs(qr-t[p].Max[1]));
    103     return dis;
    104 }
    105 
    106 inline void kd_query_max(int p){
    107     int dl,dr,d0;
    108     d0=abs(t[p].d[0]-ql)+abs(t[p].d[1]-qr);
    109     if(d0>ans) ans=d0;
    110 
    111     if(t[p].l) dl=dis_max(t[p].l); else dl=0;
    112     if(t[p].r) dr=dis_max(t[p].r); else dr=0;
    113 
    114     if(dl>dr) {
    115     if(dl>ans) kd_query_max(t[p].l);
    116     if(dr>ans) kd_query_max(t[p].r);
    117     }
    118     else{
    119     if(dr>ans) kd_query_max(t[p].r);
    120     if(dl>ans) kd_query_max(t[p].l);
    121     }
    122 }
    123 
    124 int main()
    125 {
    126   n=getint();
    127   for(int i=1;i<=n;i++) t[i].d[0]=getint(),t[i].d[1]=getint();
    128   root=kd_build(1,n,0); zong=inf;
    129   for(int i=1;i<=n;i++) {
    130       ans=inf;  ql=t[i].d[0]; qr=t[i].d[1];
    131       kd_query_min(root); ans2=ans; ans=0;
    132       kd_query_max(root);
    133       zong=min(zong,ans-ans2);
    134   }
    135   printf("%d",zong);
    136   return 0;
    137 }
  • 相关阅读:
    14_java之变量|参数|返回值|修饰符
    NYOJ 202 红黑树 (二叉树)
    NYOJ 138 找球号(二) (哈希)
    NYOJ 136 等式 (哈希)
    NYOJ 133 子序列 (离散化)
    NYOJ 129 树的判定 (并查集)
    NYOJ 117 求逆序数 (树状数组)
    NYOJ 93 汉诺塔 (数学)
    HDU 2050 折线分割平面 (数学)
    天梯赛L2-008 最长对称子串 (字符串处理)
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5820789.html
Copyright © 2011-2022 走看看