ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ABC273 D] LRUD Instructions
    문제 풀이/AtCoder 2023. 2. 7. 17:31

    난이도: 1119

     

    태그

    더보기
    • Implementation (구현 난이도 조금 있는 편)
    • Coordinate Compression
    • Binary Search

     

    풀이

    1. 1차원 버전의 문제를 풀어보자.

    더보기

    \( 1 \)부터 \( X \)까지의 칸이 있고, 여기에는 \( N \)개의 장애물이 있다고 해봅시다.

    \( i \)번째 장애물은 \( P_{i} \)에 위치해있으며, 우리가 처리해야 하는 쿼리는

    \( dir \) \( x \) \( l \): \( x \)에서 출발해서 \( dir \) 방향으로 \( l \)칸 이동 후 도착하는 위치 출력

    입니다.

     

    모든 쿼리에 대해, 이동 결과는 아래 셋 중 하나로 나오게 됩니다.

    • \( l \)칸을 이동하는 동안 장애물을 만나지 않음
    • 장애물을 만나서 도중에 멈춤
    • 마지막 칸에 다다라서 멈춤

     

    잠시 \( dir \)이 R로 고정되었다고 해봅시다.

    그럼, 각각의 경우에 대한 최종 위치는 아래와 같이 표현할 수 있습니다.

    • \( l \)칸을 이동하는 동안 장애물을 만나지 않음: \( x+l \)
    • 장애물을 만나서 도중에 멈춤: \( \min\limits_{x<P_{i}} P_{i} - 1 \)
    • 마지막 칸에 다다라서 멈춤: \( X \)

     

    최종적으로 멈추게 되는 위치는 위 셋 중 최솟값의 위치가 됩니다.

     

    \( dir \)이 L인 경우는 R인 경우와 비슷하니, 비슷하게 처리해주면 됩니다.

     

    2. 2차원으로 확장시켜봅시다.

    더보기

    문제에서 주는 상황은 2차원이기 때문에, 좀 더 생각이 필요할 거 같습니다.

     

    그런데, 가능한 이동 방향은 항상 \( y \)축 또는 \( x \)축에 평행합니다.

    이게 중요한 이유는, \( x \)축에 평행한 이동은 \( y \)좌표가 시작할 때의 \( y \)와 동일한 장애물만 남긴 뒤 1차원의 이동을 적용시키면 됩니다.

    \( y \)축의 이동도 비슷하게 처리해주면 되겠죠.

     

    3. 구현 디테일

    더보기

    위를 처리하는 가장 간단한 방법은 \( Y_{x} \) = 고정된 \( x \)에 대해 \( (y, x) \)가 장애물인 모든 \( y \)의 위치 를 저장하고, (\( X_y \)도 비슷한 방식으로 저장)

    \( y \) 방향으로 이동할 때는 [1]에서 고려한 3가지를 계산해주는 것입니다.

     

    이 때 2번째 경우 (장애물을 만나서 멈추는 경우)는 효율적으로 구현하기 위해서는 \( Y \) 배열에서 이진 탐색을 진행해줘야겠죠.

     

    하지만 좌표의 범위가 \( 10^9 \)까지 갈 수 있으니, 뭔가가 더 필요해 보입니다.

     

    생각해보면, 좌표의 범위가 \( 10^9 \)까지 가더라도, 장애물의 개수는 최대한 \( 200\,000 \)개이기 때문에

    대부분의 좌표에 대해서는 "장애물 없음", 즉 \( Y \) 배열을 고려할 필요 없음 이 됩니다.

     

    그러니, 실제로 장애물이 있는 \( y, x \)좌표들에 대해 좌표 압축을 해주고, 이 값을 \( Y \)의 인덱스로 넣어주면 됩니다.

    만약 인덱스에 없는 값이 나왔다면, 장애물이 없는 것이니 패스해주면 되죠.

     

    4. 구현

    더보기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    map<intint> cvty, cvtx; set<int> sy, sx;
    vector<int> vy[200020], vx[200020];
     
    pi2 arr[200020];
     
    void Main(){
        int h, w, y, x; cin >> h >> w >> y >> x;
        int n; cin >> n;
        for (int i = 1; i <= n; i++){
            cin >> arr[i].fr >> arr[i].sc;
            sy.insert(arr[i].fr); sx.insert(arr[i].sc);
        }
        int cy = 0for (int a : sy){ cvty[a] = ++cy; }
        int cx = 0for (int a : sx){ cvtx[a] = ++cx; }
        for (int i = 1; i <= n; i++){
            vy[ cvtx[arr[i].sc] ].push_back(arr[i].fr);
            vx[ cvty[arr[i].fr] ].push_back(arr[i].sc);
        }
        for (int i = 1; i <= cy; i++){ sort(all(vx[i])); }
        for (int i = 1; i <= cx; i++){ sort(all(vy[i])); }
        int q; cin >> q; while (q--){
            char dir; int dst; cin >> dir >> dst;
            if (dir == 'U'){
                if (cvtx.count(x) == 0){ y = max(y-dst, 1); }
                else{
                    int px = cvtx[x];
                    auto idx = lower_bound(all(vy[px]), y) - vy[px].begin();
                    y = max(y-dst, (idx==0 ? 1 : vy[px][idx-1]+1));
                }
            }
            if (dir == 'D'){
                if (cvtx.count(x) == 0){ y = min(y+dst, h); }
                else{
                    int px = cvtx[x];
                    auto idx = lower_bound(all(vy[px]), y) - vy[px].begin();
                    y = min(y+dst, (idx==vy[px].size() ? h : vy[px][idx]-1));
                }
            }
            if (dir == 'L'){
                if (cvty.count(y) == 0){ x = max(x-dst, 1); }
                else{
                    int py = cvty[y];
                    auto idx = lower_bound(all(vx[py]), x) - vx[py].begin();
                    x = max(x-dst, (idx==0 ? 1 : vx[py][idx-1]+1));
                }
            }
            if (dir == 'R'){
                if (cvty.count(y) == 0){ x = min(x+dst, w); }
                else{
                    int py = cvty[y];
                    auto idx = lower_bound(all(vx[py]), x) - vx[py].begin();
                    x = min(x+dst, (idx==vx[py].size() ? w : vx[py][idx]-1));
                }
            }
            cout << y << ' ' << x << endl;
        }
    }
    cs

    '문제 풀이 > AtCoder' 카테고리의 다른 글

    [AtCoder - ABC285 A] Edge Checker 2  (0) 2023.02.23
    [AtCoder - ABC279 F] BOX  (0) 2023.02.09
    [ARC148 A] mod M  (0) 2023.02.05
    [ARC030 1] 閉路グラフ  (0) 2023.02.04
    [ABC182A] twiblr  (0) 2023.02.03
Designed by Tistory.