题解
- 题目大意就是在一个平面直角坐标系中x轴上是一道屏障,但上面有n个开头,要求两个点的距离
- 显然,这题可以分类讨论来做
- ①两个点的y坐标同号,直接求曼哈顿距离输出
- 如果不行,则二分一个在中间的开口
- ②如果这个开口位于两个点中间,求出两个点分别到开口的曼哈顿距离相加并输出
- ③否则判断一下它距离哪一个端点近,就由哪里绕过去
- 虽然此时的pos值不一定准确,但十分接近,真实值一定出现在pos-1,pos,pos+1中,求最小值输出就好了
代码
1 #include<cstdio>
2 #include<iostream>
3 #include<algorithm>
4 using namespace std;
5 int n,m,a[100010];
6 int abs(int a){ return a<0?-a:a;}
7 int find(int x)
8 {
9 int l=1,r=n,k=n;
10 while(l<=r)
11 {
12 int mid=(l+r)/2;
13 if(a[mid]<x) l=mid+1; else r=mid-1,k=mid;
14 }
15 return k;
16 }
17 int main()
18 {
19 int x1,x2,y1,y2;
20 scanf("%d",&n);
21 for(int i=1;i<=n;i++) scanf("%d",&a[i]);
22 sort(a+1,a+n+1);
23 scanf("%d",&m);
24 for(int i=1;i<=m;i++)
25 {
26 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
27 if((y1<0&&y2<0)||(y1>0&&y2>0))
28 {
29 printf("%d
",abs(y1-y2)+abs(x1-x2));
30 continue;
31 }
32 if(x1>x2) swap(x1,x2);
33 int pos=find((x1+x2)/2);
34 if(a[pos]>=x1&&a[pos]<=x2 )printf("%d
",abs(y1-y2)+abs(x1-x2));
35 else
36 {
37 int t1=abs(a[pos]-x1)+abs(a[pos]-x2)+abs(y1-y2),t2=0x7fffffff,t3=0x7fffffff;
38 if(pos>1) t2=abs(a[pos-1]-x1)+abs(a[pos-1]-x2)+abs(y1-y2);
39 if(pos<n) t3=abs(a[pos+1]-x1)+abs(a[pos+1]-x2)+abs(y1-y2);
40 if(t1>t2) t1=t2;
41 if(t1>t3) t1=t3;
42 printf("%d
",t1);
43 }
44 }
45 }