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 }
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: