Treasure Hunting
Problem Description
You are on the island which can be represented as a n × m n×m n×m table. The rows are numbered from 1 to n and the columns are numbered from 1 to m. There are k treasures on the island, the i-th of them is located at the position ( r i , c i ) (r_i,c_i) (ri,ci).
Initially you stand at the lower left corner of the island, at the position ( 1 , 1 ) (1,1) (1,1). If at any moment you are at the cell with a treasure, you can pick it up without any extra time. In one move you can move up (from ( r , c ) (r,c) (r,c) to ( r + 1 , c ) (r+1,c) (r+1,c)), left (from ( r , c ) (r,c) (r,c) to ( r , c − 1 ) (r,c−1) (r,c−1)), or right (from position ( r , c ) (r,c) (r,c) to ( r , c + 1 ) (r,c+1) (r,c+1)). Because of the traps, you can’t move down.
However, moving up is also risky. You can move up only if you are in a safe column. There are q safe columns: b 1 , b 2 , … , b q b_1,b_2,…,b_q b1,b2,…,bq. You want to collect all the treasures as fast as possible. Count the minimum number of moves required to collect all the treasures.
Input
The first line contains integers n n n, m m m, k k k and q q q ( 2 ≤ n , m , k , q ≤ 2 ⋅ 1 0 5 2≤n,m,k,q≤2⋅10^5 2≤n,m,k,q≤2⋅105, q ≤ m q≤m q≤m) — the number of rows, the number of columns, the number of treasures in the island and the number of safe columns.
Each of the next k lines contains two integers r i r_i ri, c i c_i ci, ( 1 ≤ r i ≤ n 1≤r_i≤n 1≤ri≤n, 1 ≤ c i ≤ m 1≤c_i≤m 1≤ci≤m) — the coordinates of the cell with a treasure. All treasures are located in distinct cells.
The last line contains q distinct integers b 1 , b 2 , … , b q b_1,b_2,…,b_q b1,b2,…,bq ( 1 ≤ b i ≤ m 1≤b_i≤m 1≤bi≤m) — the indices of safe columns.
Output
Print the minimum number of moves required to collect all the treasures.
Sample Input
3 3 3 2
1 1
2 1
3 1
2 3
Sample Output
6
题意
在一个大小为n*m的地图内,有k个宝箱,坐标分别为 ( x i , y i ) (x_i,y_i) (xi,yi)。左下角坐标为(1,1),右上角坐标为(n,m),初始在左下角。每次可以向左、右、上移动一步,但向上移动有限制,只有在固定列才能向上移动,共有q列,分别为 b 1 , b 2 , . . . b q b_1,b_2,...b_q b1,b2,...bq。求拿到所有宝箱的最少步。
题解:
因为不能向下走,所以在一行时,需要把那一行的宝箱都拿完,再向上去其他行,向上移动的步数一一共为
x
m
a
x
−
1
x_{max}-1
xmax−1步。
对于同一行的宝箱,其纵坐标分别为
y
1
,
y
2
.
.
.
.
y
s
y_1,y_2....y_s
y1,y2....ys,拿完本行的所有宝箱一定停留在
y
m
i
n
y_{min}
ymin或
y
m
a
x
y_{max}
ymax的位置。设前一行拿完所有宝箱,停留在
l
l
l位置,最小代价为
a
l
al
al,停留在
r
r
r位置,最小代价为
a
r
ar
ar。设
l
l
l左边与
l
l
l最近的能向上走的列为
p
o
s
1
pos1
pos1,右边为
p
o
s
2
pos2
pos2。从l出发停留在
y
m
i
n
y_{min}
ymin的代价为
a
l
+
∣
l
−
p
o
s
1
∣
+
∣
p
o
s
1
−
y
m
a
x
∣
+
∣
y
m
a
x
−
y
m
i
n
∣
al+|l-pos1|+|pos1-y_{max}|+|y_{max}-y_{min}|
al+∣l−pos1∣+∣pos1−ymax∣+∣ymax−ymin∣或
a
l
+
∣
l
−
p
o
s
2
∣
+
∣
p
o
s
2
−
y
m
a
x
∣
+
∣
y
m
a
x
−
y
m
i
n
∣
al+|l-pos2|+|pos2-y_{max}|+|y_{max}-y_{min}|
al+∣l−pos2∣+∣pos2−ymax∣+∣ymax−ymin∣。
停留在
y
m
a
x
y_{max}
ymax同理。
从
r
r
r出发同理。
更新
l
,
r
,
a
l
,
a
r
l,r,al,ar
l,r,al,ar即可。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-7
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 200100;
const int mod = 1000000007;
struct node{
int x, y;
}p[maxn];
int b[maxn];
bool cmp(node a, node b);
LL dis(int a, int b, int c, int d);
int main()
{
int n, m, q, i, j, k, l, r;
LL ans = 0, al, ar;
scanf("%d %d %d %d", &n, &m, &k, &q);
for(i=0;i<k;i++)
scanf("%d %d", &p[i].x, &p[i].y);
for(i=0;i<q;i++)
scanf("%d", &b[i]);
sort(p, p+k, cmp);
sort(b, b+q);
i=0;
l = r = 1;
while(i<k && p[i].x == 1){
l = r = max(r, p[i].y);
i++;
}
al = ar = r-1;
for(;i<k;){
int mx = -1, mi = INF;
LL ax = 1e18, ai = 1e18;
for(j=i;j<k && p[j].x == p[i].x;j++)
mx = max(mx, p[j].y), mi = min(mi, p[j].y);
i = j;
int pos = upper_bound(b, b+q, l)-b;
if(pos != q){
ax = min(ax, al+dis(l, b[pos], mi, mx));
ai = min(ai, al+dis(l, b[pos], mx, mi));
}
if(pos != 0){
ax = min(ax, al+dis(l, b[pos-1], mi, mx));
ai = min(ai, al+dis(l, b[pos-1], mx, mi));
}
pos = upper_bound(b, b+q, r)-b;
if(pos != q){
ax = min(ax, ar+dis(r, b[pos], mi, mx));
ai = min(ai, ar+dis(r, b[pos], mx, mi));
}
if(pos != 0){
ax = min(ax, ar+dis(r, b[pos-1], mi, mx));
ai = min(ai, ar+dis(r, b[pos-1], mx, mi));
}
l = mi, r = mx;
al = ai, ar = ax;
}
printf("%I64d\n", min(al, ar)+p[k-1].x-1);
return 0;
}
LL dis(int a, int b, int c, int d)
{
return abs(a-b)+abs(b-c)+abs(c-d);
}
bool cmp(node a, node b)
{
return a.x < b.x;
}