Submission #386306

#TimeUsernameProblemLanguageResultExecution timeMemory
386306model_codeEscape Route (JOI21_escape_route)C++17
100 / 100
2077 ms278024 KiB
#include "escape_route.h"
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)
const long long inf = 1000000000000000000;

#define N_MAX 90
#define M_MAX (N_MAX * (N_MAX - 1) / 2)
#define Q_MAX 3000000

class Path {
public:
    long long l, c, d;
    Path(): l(inf * 2), c(0), d(-inf * 2) {}
    Path(long long _l, long long _c): l(_l), c(_c), d(_c - _l) {}
};

int n, m;
long long s;
Path ps[N_MAX][N_MAX];
tuple<int, int, Path> pl[M_MAX];
long long reach[N_MAX][N_MAX];
long long from0[N_MAX][N_MAX];
long long latest_first[N_MAX][M_MAX * 2];
long long latest_second[M_MAX * 2][N_MAX];
vector<pair<long long, int>> query[N_MAX][N_MAX];
int ql[Q_MAX];
vector<long long> answer;

long long require_time(Path p, long long t) {
    t = t % s;
    if(t <= p.d) {
        return p.l;
    } else {
        return s + p.l - t;
    }
}
long long require_time_oneday(Path p, long long t) {
    if(t <= p.d) {
        return p.l;
    } else {
        return inf;
    }
}
long long require_time_oneday_reverse(Path p, long long t) {
    if(t < p.l) {
        return inf;
    } else if(t > p.c) {
        return t - p.d;
    } else {
        return p.l;
    }
}

void prepare_overday_reverse(int x) {
    vector<long long> z(n, -1);
    vector<bool> un(n, true);
    int now = x;
    z[x] = s - 1;
    while(now >= 0) {
        un[now] = false;
        long long nt = z[now];
        int next = -1;
        long long current = -1;
        rep(i, n) {
            if(un[i]) {
                z[i] = max(z[i], nt - require_time_oneday_reverse(ps[now][i], nt));
                if(current < z[i]) {
                    current = z[i];
                    next = i;
                }
            }
        }
        now = next;
    }
    rep(i, n) {
        reach[i][x] = z[i];
    }
}
void prepare_overday(int x) {
    vector<long long> z(n, inf);
    vector<bool> un(n, true);
    int now = x;
    z[x] = 0;
    while(now >= 0) {
        un[now] = false;
        long long nt = z[now];
        int next = -1;
        long long current = inf;
        rep(i, n) {
            if(un[i]) {
                z[i] = min(z[i], nt + require_time(ps[now][i], nt));
                if(current > z[i]) {
                    current = z[i];
                    next = i;
                }
            }
        }
        now = next;
    }
    rep(i, n) {
        from0[i][x] = z[i];
    }
}
void prepare_overday() {
    rep(i, n) {
        prepare_overday_reverse(i);
        prepare_overday(i);
    }
}
void prepare_oneday_reverse(int x, long long t, int w) {
    vector<long long> z(n, -1);
    vector<bool> un(n, true);
    int now = w;
    z[w] = t;
    while(now >= 0) {
        un[now] = false;
        long long nt = z[now];
        int next = -1;
        long long current = -1;
        rep(i, n) {
            if(un[i]) {
                z[i] = max(z[i], nt - require_time_oneday_reverse(ps[now][i], nt));
                if(current < z[i]) {
                    current = z[i];
                    next = i;
                }
            }
        }
        now = next;
    }
    rep(i, n) {
        latest_first[i][x] = z[i];
    }
}
void prepare_oneday(int x, long long t, int w) {
    vector<long long> z(n, inf);
    vector<bool> un(n, true);
    int now = w;
    z[w] = t;
    while(now >= 0) {
        un[now] = false;
        long long nt = z[now];
        int next = -1;
        long long current = inf;
        rep(i, n) {
            if(un[i]) {
                z[i] = min(z[i], nt + require_time_oneday(ps[now][i], nt));
                if(current > z[i]) {
                    current = z[i];
                    next = i;
                }
            }
        }
        now = next;
    }
    rep(i, n) {
        latest_second[x][i] = z[i];
    }
}
void prepare_oneday() {
    rep(i, m) {
        prepare_oneday_reverse(i * 2, get<2>(pl[i]).c, get<0>(pl[i]));
        prepare_oneday_reverse(i * 2 + 1, get<2>(pl[i]).c, get<1>(pl[i]));
        prepare_oneday(i * 2, get<2>(pl[i]).c, get<0>(pl[i]));
        prepare_oneday(i * 2 + 1, get<2>(pl[i]).c, get<1>(pl[i]));
    }
}
void prepare() {
    prepare_overday();
    prepare_oneday();
}

void solve_overday(int u, int v) {
    vector<pair<long long, long long>> w;
    rep(i, n) {
        if(reach[u][i] >= 0) {
            w.push_back(make_pair(reach[u][i], from0[v][i]));
        }
    }
    for(auto i: query[u][v]) {
        w.push_back(make_pair(i.first, i.second - inf));
    }
    sort(w.begin(), w.end(), greater<pair<long long, long long>>());
    long long now = inf;
    for(auto i: w) {
        if(i.second < 0) {
            answer[i.second + inf] = min(answer[i.second + inf], s - i.first + now);
        } else {
            now = min(now, i.second);
        }
    }
    for(auto i: w) {
        if(i.second < 0) {
            answer[i.second + inf] = min(answer[i.second + inf], s * 2 - i.first + now);
        }
    }
}
void solve_oneday(int u) {
    vector<pair<long long, long long>> w;
    rep(i, m * 2) {
        if(latest_first[u][i] >= 0) {
            w.push_back(make_pair(latest_first[u][i], i));
        }
    }
    rep(i, n) {
        for(auto j: query[u][i]) {
            w.push_back(make_pair(j.first, j.second - inf));
        }
    }
    sort(w.begin(), w.end(), greater<pair<long long, long long>>());
    vector<long long> now(n, inf);
    for(auto i: w) {
        if(i.second < 0) {
            int idx = i.second + inf;
            answer[idx] = min(answer[idx], now[ql[idx]]);
        } else {
            rep(j, n) {
                now[j] = min(now[j], latest_second[i.second][j] - i.first);
            }
        }
    }
    for(auto i: w) {
        if(i.second < 0) {
            int idx = i.second + inf;
            answer[idx] = min(answer[idx], s - i.first + now[ql[idx]]);
        }
    }
}
void solve(int q) {
    answer.resize(q, inf);
    rep(i, n) {
        rep(j, n) {
            if(i != j) {
                solve_overday(i, j);
            }
        }
    }
    rep(i, n) {
        solve_oneday(i);
    }
}

vector<long long> calculate_necessary_time(
    int N, int M, long long S, int Q, vector<int> A, vector<int> B,
    vector<long long> L, vector<long long> C, vector<int> U,
    vector<int> V, vector<long long> T) {
    n = N;
    m = M;
    s = S;
    rep(i, m) {
        Path p(L[i], C[i]);
        ps[A[i]][B[i]] = p;
        ps[B[i]][A[i]] = p;
        pl[i] = make_tuple(A[i], B[i], p);
    }
    rep(i, Q) {
        query[U[i]][V[i]].push_back(make_pair(T[i], i));
        ql[i] = V[i];
    }
    prepare();
    solve(Q);
    return answer;
}
#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...