bzoj 1941: [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

 

 

思路: 最近在看一些和启发式有关的题目,无意间看到了kd树,就做了一下最近点对问题,然后学习了一下kd树,kd树确实是一个很奇妙的树,可以说是一个大暴力的写法吧,不过他可以为k维空间的信息,这个还是比较牛逼的。 

在处理每个点的最近点问题和最远点问题的时候,用了一个估价函数,类似启发式搜索,把时间复杂度降低到了神奇的$O(nlogn)$,随机数据的前提,而且常数还是有点大的。 

找了网上的一些资料学习kd树,发现要么讲的很复杂,那么讲的很简单,后来找到了清华的一个课件,终于看懂了。 

kd树类似线段树,也和平衡树很像,所以可以处理很多问题。 

K-D Tree 的重构 K-D Tree 替代树套树 K-D Tree 替代可持久化树套树 K-D Tree 替代重量平衡树套线段树维护凸包 练习:K-D Tree 优化 Dp

这些都是清华课件里面讲的东西,好像有点难,慢慢做了。 

  1 #include<bits/stdc++.h>
  2 using namespace std;  
  3 int const N=500000+100;  
  4 int const inf=1e9;  
  5 int x[N],y[N],cur,n,root;  
  6 struct node{
  7     int d[2],mx[2],my[2],ch[2];   
  8     bool operator < ( const node &rhs) const{
  9         return d[cur]<rhs.d[cur];  
 10     }    
 11 }p[N]; 
 12 struct kdtree{
 13     node t[N],T;  
 14     int ans; 
 15     void update(int mid){
 16         int l=t[mid].ch[0]; 
 17         int r=t[mid].ch[1];  
 18         if(l){
 19             t[mid].mx[0]=min(t[mid].mx[0],t[l].mx[0]);  
 20             t[mid].mx[1]=max(t[mid].mx[1],t[l].mx[1]);  
 21             t[mid].my[0]=min(t[mid].my[0],t[l].my[0]);  
 22             t[mid].my[1]=max(t[mid].my[1],t[l].my[1]);  
 23         }  
 24         if(r){
 25             t[mid].mx[0]=min(t[mid].mx[0],t[r].mx[0]);  
 26             t[mid].mx[1]=max(t[mid].mx[1],t[r].mx[1]); 
 27             t[mid].my[0]=min(t[mid].my[0],t[r].my[0]); 
 28             t[mid].my[1]=max(t[mid].my[1],t[r].my[1]);  
 29         } 
 30     } 
 31     int build(int l,int r,int x){
 32         cur=x;  
 33         int mid=(l+r)/2;  
 34         nth_element(p+l,p+mid,p+r+1);  
 35         t[mid]=p[mid];   
 36         t[mid].mx[0]=t[mid].mx[1]=t[mid].d[0];  
 37         t[mid].my[0]=t[mid].my[1]=t[mid].d[1];  
 38         if(l<mid) t[mid].ch[0]=build(l,mid-1,x^1); 
 39         if(mid<r) t[mid].ch[1]=build(mid+1,r,x^1);  
 40         update(mid); 
 41         return mid; 
 42     }  
 43     int dist(node t1,node t2){
 44         return abs(t1.d[0]-t2.d[0])+abs(t1.d[1]-t2.d[1]); 
 45     } 
 46     int calcmin(node x){
 47         int ret=0; 
 48         ret+=max(x.mx[0]-T.d[0],0);  
 49         ret+=max(T.d[0]-x.mx[1],0); 
 50         ret+=max(x.my[0]-T.d[1],0); 
 51         ret+=max(T.d[1]-x.my[1],0); 
 52         return ret;    
 53     }  
 54     int calcmax(node x){
 55         int d1=abs(T.d[0]-x.mx[0])+abs(T.d[1]-x.my[0]);  
 56         int d2=abs(T.d[0]-x.mx[0])+abs(T.d[1]-x.my[1]);  
 57         int d3=abs(T.d[0]-x.mx[1])+abs(T.d[1]-x.my[0]);  
 58         int d4=abs(T.d[0]-x.mx[1])+abs(T.d[1]-x.my[1]);  
 59         return max(max(d1,d2),max(d3,d4));  
 60     } 
 61     void  getmax(int k){
 62         ans=max(ans,dist(t[k],T));  
 63         int l=t[k].ch[0]; 
 64         int r=t[k].ch[1];  
 65         int dl=-inf,dr=-inf;  
 66         if(l) dl=calcmax(t[l]); 
 67         if(r) dr=calcmax(t[r]);
 68           
 69         if(dl>dr){
 70             if(dl>ans) getmax(l); 
 71             if(dr>ans) getmax(r); 
 72         }else {
 73             if(dr>ans) getmax(r);  
 74             if(dl>ans) getmax(l);  
 75         }  
 76     }
 77         
 78     void  getmin(int k){
 79         if(dist(t[k],T)) ans=min(ans,dist(t[k],T));  
 80         int l=t[k].ch[0]; 
 81         int r=t[k].ch[1];  
 82         int dl=inf,dr=inf;  
 83         if(l) dl=calcmin(t[l]);  
 84         if(r) dr=calcmin(t[r]);  
 85         if(dl<dr){
 86             if(dl<ans) getmin(l);  
 87             if(dr<ans) getmin(r);  
 88         }else {
 89             if(dr<ans) getmin(r); 
 90             if(dl<ans) getmin(l);  
 91         }   
 92     }     
 93         
 94     int query(int f,int x,int y){
 95         T.d[0]=x;T.d[1]=y;  
 96         if(f==0) ans=inf, getmin(root);  
 97         else ans=-inf,getmax(root);  
 98         return ans;  
 99     } 
100 }kd;  
101 int main(){
102     scanf("%d",&n); 
103     for(int i=1;i<=n;i++){ 
104         scanf("%d%d",&x[i],&y[i]);  
105         p[i].d[0]=x[i];  
106         p[i].d[1]=y[i];  
107     } 
108     root=kd.build(1,n,0);     
109     int ans=inf; 
110     for(int i=1;i<=n;i++){
111         int v1=kd.query(0,x[i],y[i]); 
112         int v2=kd.query(1,x[i],y[i]);  
113         ans=min(ans,v2-v1);  
114     } 
115     printf("%d\n",ans); 
116     return 0; 
117 }   
View Code

 

 

posted @ 2019-07-03 01:59  zjxxcn  阅读(218)  评论(0编辑  收藏  举报