제출 #1328123

#제출 시각아이디문제언어결과실행 시간메모리
1328123model_codeBitaro's Travel 2 (JOI25_travel2)C++20
100 / 100
1371 ms82412 KiB
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)

struct uf{
    int n;
    vector<int> par;
    uf(int n_):n(n_), par(n_, -1){}
    int root(int a){
        return par[a] <= -1 ? a : par[a] = root(par[a]);
    }
    bool same(int a, int b){
        return root(a) == root(b);
    }
    int unite(int a, int b, bool opt = false){
        a = root(a);
        b = root(b);
        if (a == b) return 0;
        if (opt && par[a] > par[b]) swap(a, b);
        par[a] += par[b];
        par[b] = a;
        return 1;
    }
};

vector<int> solve(int H, int W, int L, vector<vector<int>> &T, int Q, vector<int> &A, vector<int> &B, vector<int> &C, vector<int> &D){
    rep(i, 0, Q){
        A[i]--, B[i]--, C[i]--, D[i]--;
    }
    struct pos{
        int x;
        int y;
    };
    auto get_ind =[&](pos a) -> int {
        return a.x * W + a.y;
    };
    auto get_T = [&](pos a) -> int {
        return T[a.x][a.y];
    };
    vector<int> dx = {1, -1, 0, 0};
    vector<int> dy = {0, 0, 1, -1};
    // 1日で、どこまでいけるかを判定する
    const int X = 19;
    vector to(X, vector<int>(H * W));
    vector<pair<pos, int>> order;
    vector<vector<int>> lis(H * W);
    {
        uf U(H * W);
        vector seen(H, vector<int>(W));
        rep(i, 0, H) rep(j, 0, W){
            order.push_back({{i, j}, T[i][j] + L});
            order.push_back({{i, j}, T[i][j]});
        }
        sort(order.begin(), order.end(), [&](pair<pos, int> l, pair<pos, int> r){
            if (l.second != r.second) return l.second < r.second;
            return get_T(l.first) == l.second && get_T(r.first) != r.second;
        });
        for (auto [a, b] : order){
            if (get_T(a) == b){
                rep(k, 0, 4){
                    pos tmp = {a.x + dx[k], a.y + dy[k]};
                    if (tmp.x < 0 || tmp.y < 0 || H <= tmp.x || W <= tmp.y) continue;
                    if (seen[tmp.x][tmp.y]){
                        if (U.unite(get_ind(a), get_ind(tmp))){
                            lis[get_ind(a)].push_back(get_ind(tmp));
                        }
                    }
                }
                seen[a.x][a.y] = 1;
            }
            else{
                to[0][get_ind(a)] = U.root(get_ind(a));
            }
        }
    }
    // ダブリングの元を構築
    {
        rep(d, 1, X) rep(i, 0, H * W){
            to[d][i] = to[d - 1][to[d - 1][i]];
        }
    }

    // 並列二分探索を行う
    vector<int> ans(Q, 1);
    vector<pos> p(Q);
    rep(i, 0, Q) p[i] = {A[i], B[i]};
    for (int d = X - 1; d >= -1; d--){
        vector<vector<int>> G(H * W);
        uf U(H * W);
        rep(i, 0, Q){
            if (d != -1) G[to[d][get_ind(p[i])]].push_back(i);
            else G[get_ind(p[i])].push_back(i);
        }
        rep(rp, 0, H * W * 2){
            auto [a, b] = order[rp];
            for (auto x : lis[get_ind(a)]) U.unite(get_ind(a), x, true);
            if (get_T(a) != b){
                for (auto id : G[get_ind(a)]){
                    if (!U.same(get_ind(a), get_ind({C[id], D[id]}))){
                        p[id] = a;
                        if (d != -1) ans[id] += (1 << d);
                        else ans[id]++;
                    }
                }
            }
        }
    }

    // 出力
    for (auto &x : ans) if (x >= (1 << X)) x = -1;
    return ans;
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int H, W, L;
    cin >> H >> W >> L;
    int sw = 0;
    // if (H > W) swap(H, W), sw = 1;
    vector T(H, vector<int>(W));
    if (sw) rep(i, 0, W) rep(j, 0, H){
        cin >> T[j][i];
    }
    else rep(i, 0, H) rep(j, 0, W) {
        cin >> T[i][j];
    }
    int Q;
    cin >> Q;
    vector<int> A(Q), B(Q), C(Q), D(Q);
    rep(i, 0, Q){
        cin >> A[i] >> B[i] >> C[i] >> D[i];
        if (sw) swap(A[i], B[i]), swap(C[i], D[i]);
    }
    auto ans = solve(H, W, L, T, Q, A, B, C, D);
    for (auto x : ans) cout << x << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...