CodeForces_1201D Treasure Hunting(贪心)

Treasure Hunting

time limit per test:3 seconds
memory limit per test:256 megabytes
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,c1)), 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 2n,m,k,q2105, q ≤ m q≤m qm) — 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 1rin, 1 ≤ c i ≤ m 1≤c_i≤m 1cim) — 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 1bim) — 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 xmax1步。
对于同一行的宝箱,其纵坐标分别为 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+lpos1+pos1ymax+ymaxymin 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+lpos2+pos2ymax+ymaxymin
停留在 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值