codeforces 967 C Stairs and Elevators

题目

In the year of 30 XX participants of some world programming championship live in a single large hotel. The hotel has n floors. Each floor has m sections with a single corridor connecting all of them. The sections are enumerated from 1 to m along the corridor, and all sections with equal numbers on different floors are located exactly one above the other. Thus, the hotel can be represented as a rectangle of height n and width m. We can denote sections with pairs of integers (i,j) , where i is the floor, and j is the section number on the floor.

The guests can walk along the corridor on each floor, use stairs and elevators. Each stairs or elevator occupies all sections (1,x) , (2,x) , …, (n,x) for some x between 1 and m . All sections not occupied with stairs or elevators contain guest rooms. It takes one time unit to move between neighboring sections on the same floor or to move one floor up or down using stairs. It takes one time unit to move up to v floors in any direction using an elevator. You can assume you don’t have to wait for an elevator, and the time needed to enter or exit an elevator is negligible.

You are to process q queries. Each query is a question “what is the minimum time needed to go from a room in section (x1,y1) to a room in section (x2,y2) ?”

Input

The first line contains five integers n , m , cl , ce , v (2≤ n , m ≤10 8 , 0 ≤ cl , ce ≤ 10 5 , 1 ≤ cl + ce m −1, 1 ≤ v n −1) — the number of floors and section on each floor, the number of stairs, the number of elevators and the maximum speed of an elevator, respectively.

The second line contains cl integers l1 ,…, lcl in increasing order (1≤ li m ), denoting the positions of the stairs. If cl =0, the second line is empty.

The third line contains ce integers e1 ,…, ece in increasing order, denoting the elevators positions in the same format. It is guaranteed that all integers li and ei are distinct.

The fourth line contains a single integer q (1 ≤ q ≤ 10 5 ) — the number of queries.

The next q lines describe queries. Each of these lines contains four integers x1 , y1 , x2 , y2 (1≤ x1 , x2 n , 1≤ y1 , y2 m ) — the coordinates of starting and finishing sections for the query. It is guaranteed that the starting and finishing sections are distinct. It is also guaranteed that these sections contain guest rooms, i. e. y1 and y2 are not among li and ei .

Output

Print q integers, one per line — the answers for the queries.

Example

Input
5 6 1 1 3
2
5
3
1 1 5 6
1 3 5 4
3 3 5 3
Output
7
5
4

Note

In the first query the optimal way is to go to the elevator in the 5-th section in four time units, use it to go to the fifth floor in two time units and go to the destination in one more time unit.

In the second query it is still optimal to use the elevator, but in the third query it is better to use the stairs in the section 2.


分析

题意:给一个酒店,有 n 层楼,每层有 m 个位置,已知楼梯和电梯的位置,并且它们贯穿1~n楼,剩下的位置都是客房,电梯1个时间单位走 v 层楼。问从 x1 层的 y1 房间到 x2 层的 y2 房间最短需要多久。

分析:楼层之间最优的移动方案一定是下面四个中的一个

  • 乘y1左边最近的电梯
  • 乘y1右边最近的电梯
  • 走y1左边最近的楼梯
  • 走y1右边最近的楼梯

由于电梯可能在很远的位置,所以走楼梯的情况也必须考虑。
所以,把四个方案的代价计算出来取最优即可,由于电梯和楼梯的个数都在1e5,考虑用二分查找离y1最近的电梯/楼梯所在的位置。因为左边最近和右边最近的位置是相邻的,所以用二分查找一次就可以完成。

注意:需要特判起点和终点在同一层楼的情况;以及电梯/楼梯没有的时候,不能自己生成一个电梯/楼梯来使用(划掉)

代码

#include
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mabs(x) ((x)>0?(x):(0-(x)))
#define N_max 100005

/*
*n层楼
*每层楼m个房间,按1~m编号,相同编号的水平位置相同
*把房间表示为(i, j),意思是i层楼的j房间
*在走廊上走,走楼梯或坐电梯
*每个x的楼梯或电梯占有了所有(i, x)
*房间之间或层之间走动1花费1,坐电梯走动v花费1
*查询:从(x1, y1)到(x2, y2)
*/
int n, m, cl, ce, v, q;
int flr[100005], elv[100005];
//二分查找一次完成对左右电梯/楼梯的查找
void bins(int a[], int n, int x,int *_l,int *_r) {
    int l = -1, r = n, m;
    //二分求l,是左边最近的位置
    while (l + 1 < r) {
        m = (l + r) / 2;
        if (a[m] <= x)l = m;
        else r = m;
    }

    if (l == -1)//没有在x左边的电梯/楼梯,选一个最左边的来代替
        l = 0;

    //求r,是与l相邻的位置
    if (a[l] == x)//如果l是x的位置,那么使用该电梯/楼梯是最优的
        r = l;
    //没有在x右边的电梯/楼梯,选一个最右边的来代替
    else r = (l + 1 )>= n ? n - 1 : l + 1;
    //传递结果
    *_l=l;*_r=r;
}


int sol(int x1, int y1, int x2, int y2) {
    int l, r;
    int costf, coste;
    int cost1, cost2, cost3;
    //同一层楼特判
    if (x1 == x2)
        return mabs(y1 - y2);

    //走左右最近的楼梯
    bins(flr, cl, y1,&l,&r);
    costf = min(mabs(y1 - flr[l]) + mabs(x2 - x1) + mabs(y2 - flr[l]),
                mabs(y1 - flr[r]) + mabs(x2 - x1) + mabs(y2 - flr[r]));

    //左右最近的电梯
     bins(elv, ce, y1,&l,&r);
    coste = min(mabs(y1 - elv[l]) + mabs(x2 - x1) / v + (mabs(x2 - x1) % v != 0) + mabs(y2 - elv[l]),
                mabs(y1 - elv[r]) + mabs(x2 - x1) / v + (mabs(x2 - x1) % v != 0) + mabs(y2 - elv[r]));
    //该解法没有考虑电梯/楼梯没有的情况,在最后判断
    if (cl == 0)return coste;
    else if (ce == 0)return costf;
    return min(costf, coste);
}
int main() {

    int x1, y1, x2, y2;
    scanf("%d %d %d %d %d", &n, &m, &cl, &ce, &v);
    for (int i = 0; i < cl; ++i)
        scanf("%d", &flr[i]);
    for (int i = 0; i < ce; ++i)
        scanf("%d", &elv[i]);
    scanf("%d", &q);
    int ans;
    for (int i = 0; i < q; ++i) {
        scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
        ans = sol(x1, y1, x2, y2);
        printf("%d\n", ans);

    }
}

你可能感兴趣的:(acm,codeforces)