KD-tree 总结

T1:Hide and Seek

题干:

  小猪 $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$ 的问题。

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

  输出格式:一个整数,为距离差的最小值。

题解:

  求两点距离,比较简单地就可以想到用 $K-D tree$来解决。

  这道题要求出距离差,我们就可以用 $K-D tree$ 维护一下矩阵最大值与最小值,不断更新答案即可。

  时间复杂度 $\Theta(n\sqrt{n})$

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define $ 500100
 5 #define inf 0x7fffffff
 6 using namespace std;
 7 int n,ans=inf,now,siz,maxx,minn;
 8 struct node{    int x[2];    }a[$];
 9 inline int abss(int x)     {    return (x<0)?-x:x;    }
10 inline int max(int x,int y){    return (x>y)?x:y;    }
11 inline int min(int x,int y){    return (x<y)?x:y;    }
12 inline int mid(int x,int y){    return (x+y)>>1;    }
13 inline bool cmp(const node &a,const node &b){    
14     return a.x[now]<b.x[now];
15 }
16 inline int dis(node a,node b){
17     return abss(a.x[0]-b.x[0])+abss(a.x[1]-b.x[1]);
18 }
19 inline int read(){
20     int a=0;
21     char s=getchar();
22     while(s>'9'||s<'0')   s=getchar();
23     while(s<='9'&&s>='0') a=(a<<1)+(a<<3)+(s^48), s=getchar();
24     return a;
25 }
26 struct tree{    
27     tree *son[2];
28     node pint;
29     int imax[2],imin[2];
30     inline void init(node a){
31         pint=a; son[0]=son[1]=NULL;
32         imin[0]=imax[0]=a.x[0], imin[1]=imax[1]=a.x[1];
33     }
34     inline void update(tree *a){
35         imin[0]=min(imin[0],a->imin[0]), imin[1]=min(imin[1],a->imin[1]);
36         imax[0]=max(imax[0],a->imax[0]), imax[1]=max(imax[1],a->imax[1]);
37     }
38     inline void pushup(){
39         if(son[0]!=NULL) update(son[0]);
40         if(son[1]!=NULL) update(son[1]);
41     }
42     inline int cal_min(node a){
43         return max(imin[0]-a.x[0],0)+max(a.x[0]-imax[0],0)
44               +max(imin[1]-a.x[1],0)+max(a.x[1]-imax[1],0);
45     }
46     inline int cal_max(node a){
47         return max(abss(a.x[0]-imin[0]),abss(a.x[0]-imax[0]))
48               +max(abss(a.x[1]-imin[1]),abss(a.x[1]-imax[1]));
49     }
50 }*root,sum[$];
51 inline void build(tree *&p,int l,int r,int d){
52     if(l>r) return;
53     p=sum+(siz++), now=d;
54     int mid=(l+r)>>1;
55     nth_element(a+l,a+mid,a+r+1,cmp);
56     p->init(a[mid]);
57     build(p->son[0],l,mid-1,d^1), build(p->son[1],mid+1,r,d^1);
58     p->pushup();
59 }
60 inline void query_max(tree *p,node b){
61     if(p==NULL) return;
62     maxx=max(dis(p->pint,b),maxx);
63     int dis[2];
64     dis[0]=(p->son[0]==NULL)?0:p->son[0]->cal_max(b);
65     dis[1]=(p->son[1]==NULL)?0:p->son[1]->cal_max(b);
66     int opt=dis[0]>dis[1]?0:1;
67     if(dis[opt]>maxx)   query_max(p->son[opt],b);
68     if(dis[opt^1]>maxx) query_max(p->son[opt^1],b);
69 }
70 inline void query_min(tree *p,node b){
71     if(p==NULL) return;
72     if(dis(p->pint,b)) minn=min(minn,dis(p->pint,b));
73     int dis[2];
74     dis[0]=(p->son[0]==NULL)?inf:p->son[0]->cal_min(b);
75     dis[1]=(p->son[1]==NULL)?inf:p->son[1]->cal_min(b);
76     int opt=dis[0]>dis[1]?0:1;
77     if(dis[opt]<minn)   query_min(p->son[opt],b);
78     if(dis[opt^1]<minn) query_min(p->son[opt^1],b);
79 }
80 inline int query_max(node b){
81     maxx=0,   query_max(root,b);
82     return maxx;
83 }
84 inline int query_min(node b){
85     minn=inf, query_min(root,b);
86     return minn;
87 }
88 signed main(){
89     n=read();
90     for(register int i=1;i<=n;++i) a[i].x[0]=read(),a[i].x[1]=read();
91     build(root,1,n,0);
92     for(register int i=1;i<=n;++i) 
93         ans=min(ans,query_max(a[i])-query_min(a[i]));
94     printf("%d\n",ans);
95 }
View Code

T2:巧克力王国

题干:

  巧克力王国里的巧克力都是由牛奶和可可做成的。但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力。对于每一块巧克力,我们设 $x$ 和 $y$ 为其牛奶和可可的含量。由于每个人对于甜的程度都有自己的评判标准,所以每个人都有两个参数 $a$ 和 $b$ ,分别为他自己为牛奶和可可定义的权重,因此牛奶和可可含量分别为 $x$ 和 $y$ 的巧克力对于他的甜味程度即为 $ax + by$。而每个人又有一个甜味限度 $c$,所有甜味程度大于等于 $c$ 的巧克力他都无法接受。每块巧克力都有一个美味值 $h$ 。现在我们想知道对于每个人,他所能接受的巧克力的美味值之和为多少

  输入格式:第一行两个正整数 $n$ 和 $m$ ,分别表示巧克力个数和询问个数;接下来 $n$ 行,每行三个整数 $x$ , $y$ , $h$ ,含义如题目所示;再接下来 $m$ 行,每行三个整数 $a$ , $b$ , $c$ 。

  输出格式:输出 $m$ 行,其中第 $i$ 行表示第 $i$ 个人所能接受的巧克力的美味值之和。

题解:

  

Code:

 

T3:JZPFAR

题干:

  平面上有 $n$ 个点。现在有 $m$ 次询问,每次给定一个点 $(px, py)$ 和一个整数 $k$ ,输出 $n$ 个点中离 $(px, py)$ 的距离第 $k$ 大的点的标号。如果有两个(或多个)点距离 $(px, py)$ 相同,那么认为标号较小的点距离较大。

  输入格式:第一行,一个整数 $n$,表示点的个数;下面 $n$ 行  ,每行两个整数 $x_i$ ,  $y_i$ ,表示 $n$ 个点的坐标。点的标号按照输入顺序,分别为 $1..n$;下面一行,一个整数 $m$,表示询问个数;下面 $m$ 行,每行三个整数 $px_i$, $py_i$, $k_i$,表示一个询问。

  输出格式: $m$ 行,每行一个整数,表示相应的询问的答案。

题解:

 

Code:

 

 

T4:K远点对

题干:

  已知平面内 $N$ 个点的坐标,求欧氏距离下的第 $K$ 远点对。

  输入格式:输入文件第一行为用空格隔开的两个整数 $N$, $K$。接下来 $N$ 行,每行两个整数 $X$ , $Y$ ,表示一个点的坐标。$1 < = N < = 100000$, $1 < = K < = 100$, $K < = N*(N−1)/2$ , $0 < = X, Y < 2^{31}$。

  输出格式:输出文件第一行为一个整数,表示第 $K$ 远点对的距离的平方(一定是个整数)。

题解:

  

Code:

猜你喜欢

转载自www.cnblogs.com/OI-zzyy/p/11299658.html