제출 #1360254

#제출 시각아이디문제언어결과실행 시간메모리
1360254iamhereforfunFurniture (JOI20_furniture)C++20
0 / 100
1 ms344 KiB
#include <bits/stdc++.h>
using namespace std;

// Using 1005 for a 1000x1000 grid to have a safe buffer
const int MAX = 1005;

int N, M, Q;
int is_blocked[MAX][MAX];
int diag_cnt[2 * MAX];
bool dead[MAX][MAX];

// A cell is "dead" if it's furniture OR if it has no path to start/end
void push_dead(int r, int c, queue<pair<int, int>>& q) {
    // Boundary check and skip if already marked
    if (r < 1 || r > N || c < 1 || c > M || dead[r][c]) return;

    // A cell is dead if:
    // 1. It cannot be reached from (1,1) -> both Top and Left are dead
    // 2. It cannot reach (N,M) -> both Bottom and Right are dead
    bool no_from_start = dead[r - 1][c] && dead[r][c - 1];
    bool no_to_end = dead[r + 1][c] && dead[r][c + 1];

    if (no_from_start || no_to_end) {
        dead[r][c] = true;
        diag_cnt[r + c]--;
        q.push({r, c});
    }
}

int main() {
    // Standard competitive programming speed boost
    ios::sync_with_stdio(0);
    cin.tie(0);

    if (!(cin >> N >> M)) return 0;

    // Initialize boundaries as "dead" to simplify logic
    for (int i = 0; i <= N + 1; i++) {
        for (int j = 0; j <= M + 1; j++) {
            dead[i][j] = true;
        }
    }

    // Mark reachable area and initialize counts
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            dead[i][j] = false;
            diag_cnt[i + j]++;
        }
    }
    
    // (1,1) and (N,M) are always reachable from themselves
    // so they shouldn't be considered "dead" by the boundary logic
    // we handle this by ensuring the "dead" check considers them special.

    queue<pair<int, int>> q;

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            int furniture;
            cin >> furniture;
            if (furniture == 1) {
                dead[i][j] = true;
                diag_cnt[i + j]--;
                q.push({i, j});
            }
        }
    }

    // Helper to process the queue and propagate "dead" status
    auto propagate = [&]() {
        while (!q.empty()) {
            pair<int, int> curr = q.front();
            q.pop();
            int r = curr.first;
            int c = curr.second;

            // Check 4 neighbors
            push_dead(r - 1, c, q);
            push_dead(r + 1, c, q);
            push_dead(r, c - 1, q);
            push_dead(r, c + 1, q);
        }
    };

    // Initial clean up of the map
    propagate();

    cin >> Q;
    while (Q--) {
        int r, c;
        cin >> r >> c;

        if (dead[r][c]) {
            // It's already useless or blocked, so placing furniture changes nothing
            cout << 1 << "\n";
        } else if (diag_cnt[r + c] > 1) {
            // There's at least one other path on this diagonal
            cout << 1 << "\n";
            dead[r][c] = true;
            diag_cnt[r + c]--;
            q.push({r, c});
            propagate();
        } else {
            // This is the last bridge on this diagonal!
            cout << 0 << "\n";
        }
    }

    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…