您的位置:首页 > 其它

jzoj1792 教主的花园 (二分)

2018-02-07 19:56 190 查看

教主的花园 (Standard IO)

Description

【问题背景】

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

【问题描述】

  可以把教主的花园附近区域抽像成一个正方形网格组成的网络,每个网格都对应了一个坐标(均为整数,有可能为负),若两个网格(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

  输入的第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

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

Sample Input

2

2 -1

2

0 1 0 -1

1 1 2 2

Sample Output

4

2

Data Constraint

Hint

【数据规模】

  对于20%的数据,有n,m≤10,ai,xi,yi绝对值不超过100;

  对于40%的数据,有n,m≤100,ai,xi,yi绝对值不超过1000;

  对于60%的数据,有n,m≤1000,ai,xi,yi绝对值不超过100000;

  对于100%的数据,有n,m≤100000,ai,xi,yi绝对值不超过100000000。

  

分析:如果两个点在一侧的话,直接算就行

如果不在一侧,先排序然后二分查找,假如能找到一个入口k使得x1<=k<=x2,那么结果就是

abs(x1-x2)+abs(y1-y2)

找不到就从选择到x1或者到x2最小的一个k

如果 k < x1,那么就writeln(abs(x1-x2)+abs(y1-y2)+abs(x1-k)*2)

如果k>x2,那就writeln(abs(x1-x2)+abs(y1-y2)+abs(x2-k)*2)

代码

#include <cstdio>
#include <algorithm>
#define ll long long
#define N 100005
using namespace std;

int n,m,a
;

ll fabs(ll x){return x>0?x:-x;}
ll min(ll x,ll y){return x<y?x:y;}

ll getsum(ll x1,ll y1,ll x2,ll y2)
{
int s=0;
if (x1>x2) s+=x1-x2;else s+=x2-x1;
if (y1>y2) s+=y1-y2;else s+=y2-y1;
return s;
}

int find1(ll x)
{
int l=1,r=n;
int ans=n;
while (l<=r)
{
int mid=(l+r)/2;
if (a[mid]==x) return mid;
if (x>=a[mid]) l=mid+1,ans=mid;
else r=mid-1;
}
return ans;
}

int find2(ll x)
{
int l=1,r=n;
int ans=n;
while (l<=r)
{
int mid=(l+r)/2;
if (a[mid]==x) return mid;
if (a[mid]>=x) r=mid-1,ans=mid;
else l=mid+1;
}
return ans;
}

int main()
{
freopen("1.in","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lld",&a[i]);
sort(a+1,a+n+1);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
ll x1,y1,x2,y2;
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
if (x1>x2)
{
x1^=x2;x2^=x1;x1^=x2;
y1^=y2;y2^=y1;y1^=y2;
}
if ((y1>0&&y2>0)||(y1<0&&y2<0))
{
printf("%lld\n",getsum(x1,y1,x2,y2));
continue;
}
if (x1<=a[1])
{
printf("%d\n",abs(y2)+abs(y1)+abs(x1-a[1])+abs(x2-a[1]));
continue;
}
if (x2>=a
)
{
printf("%d\n",abs(y2)+abs(y1)+abs(x1-a
)+abs(x2-a
));
continue;
}
if (a[find2(x1)]<=x2)
{
printf("%d\n",getsum(x1,y1,x2,y2));
continue;
}
int p1=find1(x1);
int p2=find2(x2);
ll ans;
ans=x1-a[p1]+fabs(y1)+fabs(y2)+x2-a[p1];
ans=min(ans,a[p2]-x2+fabs(y1)+fabs(y2)+a[p2]-x1);
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: