背景 Background   

LHX教主最近总困扰于前来膜拜他的人太多了,所以他给他的花园加上了一道屏障。 

 

描述 Description  

可以把教主的花园附近区域抽像成一个正方形网格组成的网络,每个网格都对应了一个坐标(均为整数,有可能为负),若两个网格(x1, y1),(x2, y2)有|x1 - x2| + |y1 - y2| = 1,则说这两个网格是相邻的,否则不是相邻的。教主在y = 0处整条直线上的网格设置了一道屏障,即所有坐标为(x, 0)的网格。当然,他还要解决他自己与内部人员的进出问题,这样教主设置了N个入口a1, a2, …, aN可供进出,即对于y = 0上的所有网格,只有 (a1, 0),(a2, 0), ……, (aN, 0) 可以通过,之外的所有纵坐标为0的网格均不能通过,而对于(x, y)有y不为0的网格可以认为是随意通过的。现在教主想知道,给定M个点对(x1, y1),(x2, y2),并且这些点均不在屏障上,询问从一个点走到另一个点最短距离是多少,每次只能从一个格子走到相邻的格子。

输入格式 Input Format 

 输入的第1行为一个正整数N,为屏障上入口的个数。第2行有N个整数,a1, a2, …, aN,之间用空格隔开,为这N个入口的横坐标。第3行为一个正整数M,表示了M个询问。接下来M行,每行4个整数x1, y1, x2, y2,有y1与y2不等于0,表示了一个询问从(x1, y1)到(x2, y2)的最短路。


输出格式 Output Format 

输出共包含m行,第i行对于第i个询问输出从(x1, y1)到(x2, y2)的最短路距离是多少。

 

这是这次模拟赛最简单的一道题,(虽然当时我出了点小错误)

 

//分两种情况,一种坐标直接相减
//一种求出距离最近的一个入口就可以啦
#include<fstream> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstdio>
#define oo 1147483647
using namespace std;
int m,n;
int a[100010],tt,ans;
int cmp(const void *a,const void *b)
{
    return *(int *)a-*(int *)b;
}
int main()
{
    freopen("orz.in","r",stdin);
    freopen("orz.out","w",stdout);
    int i;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    a[n+1]=1<<29;
    a[0]=-oo;
    qsort(a+1,n,sizeof(int),cmp);
    scanf("%d",&m);
    int x1,x2,y1,y2;
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        ans=0;
        if ((y1>0&&y2>0)||(y1<0&&y2<0))
        {
            ans=(int)abs((double)(y1-y2))+(int)abs((double)(x1-x2));
            printf("%d\n",ans);
            continue;
        }
        if (x1>x2) swap(x1,x2);
        ans=oo;
        int l=1,r=n,mid;
        while (l<=r)
        {
              mid=(l+r)>>1;
              if (a[mid]>=x1 && a[mid-1]<x1) 
              {
                  if (ans>(a[mid]-x1+abs(a[mid]-x2))) ans=a[mid]-x1+abs(a[mid]-x2);
                  if (mid>1) if (ans>(x1-a[mid-1]+abs(a[mid-1]-x2))) ans=x1-a[mid-1]+abs(a[mid-1]-x2);
                  break;
              }
              if (a[mid]<x1) l=mid+1;
              if (a[mid]>x1) r=mid-1;
        }
        l=1;r=n;mid;
        while (l<=r)
        {
              mid=(l+r)>>1;
              if (a[mid]<=x2 && a[mid+1]>x2) 
              {
                      if (ans>(x2-a[mid]+abs(x1-a[mid]))) ans=x2-a[mid]+abs(x1-a[mid]);
                      if ((mid+1)<=n)if (ans>(a[mid+1]-x2+abs(x1-a[mid+1]))) ans=a[mid+1]-x2+abs(x1-a[mid+1]);
                      break;
              }
              if (a[mid]<x2) l=mid+1;
              if (a[mid]>x2) r=mid-1;
        }
        ans+=(int)abs((double)(y1-y2));
        printf("%d\n",ans);
    }
    return 0;
}