Submission #1127963

#TimeUsernameProblemLanguageResultExecution timeMemory
1127963antonnEscape Route 2 (JOI24_escape2)C++20
100 / 100
2564 ms109068 KiB
#include <bits/stdc++.h>
 
 
using namespace std;
 
 
#define ll long long
#define ld long double
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()


const int K = 316;


int n, T, q;
vector<vector<int>> g;
vector<vector<int>> anc, f;
vector<vector<ll>> t;
vector<int> dep;
vector<int> A, B;


void dfs(int u, int p = 0) {
    anc[0][u] = p; 
    for (auto v : g[u]) {
        dep[v] = dep[u] + 1;
        dfs(v, u);
    }
}


ll join(ll t1, ll t2, int x, int y) {
    if (B[x] <= A[y]) {
        return t1 + A[y] - B[x] + t2;
    } else {
        return t1 + T - B[x] + A[y] + t2;
    }
}


int get(int x, int k) {
    for (int h = 19; h >= 0; h -= 1) {
        if (k & (1 << h)) {
            x = anc[h][x];
        }
    }
    return x;
}


ll lift(int a, int k) {
    ll ans = 0;
    int b = a;
    for (int h = 19; h >= 0; h -= 1) {
        if (k & (1 << h)) {
            if (ans == 0) {
                ans = t[h][a];
            } else {
                ans = join(ans, t[h][a], b, a);
            }
            b = f[h][a];
            a = anc[h][a];
        }
    }
    return ans;
}


vector<vector<int>> revg;
vector<vector<int>> revanc, revf;
vector<vector<ll>> revt;
vector<int> RA, RB;


void revdfs(int u, int p = 0) {
    revanc[0][u] = p;
    for (auto v : revg[u]) {
        revdfs(v, u);
    }
}


ll revjoin(ll t1, ll t2, int x, int y) { 
    if (RB[y] <= RA[x]) {
        return t1 + RA[x] - RB[y] + t2;
    } else {
        return t1 + T - RB[y] + RA[x] + t2;
    }
}


int revget(int x, int k) {
    for (int h = 19; h >= 0; h -= 1) {
        if (k & (1 << h)) {
            x = revanc[h][x];
        }
    }
    return x;
}


ll revlift(int a, int k) {
    ll ans = 0;
    int b = a;
    for (int h = 19; h >= 0; h -= 1) { 
        if (k & (1 << h)) {
            if (ans == 0) {
                ans = revt[h][a];
            } else {
                ans = revjoin(ans, revt[h][a], b, a);
            }
            b = revf[h][a];
            a = revanc[h][a];
        }
    }
    return ans;
}



int32_t main() {
    if (1) {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
  	}
    cin >> n >> T;
    vector<int> m(n + 1);
    vector<vector<pair<int, int>>> a(n + 1);
    for (int i = 1; i <= n - 1; i += 1) {
        cin >> m[i];
        a[i].resize(m[i]);
        for (int j = 0; j < m[i]; j += 1) {
            cin >> a[i][j].first >> a[i][j].second;
        }
        sort(all(a[i]));
    }
    m[n] = 1;
    a[n].push_back({T, T}); 
    vector<int> sum(n + 1);
    for (int i = 1; i <= n; i += 1) {
        sum[i] = sum[i - 1] + m[i];
    }
    auto get_id = [&](int i, int j) {
        return sum[i - 1] + j + 1;
    };

    vector<vector<pair<int, int>>> suff(n + 1);
    for (int i = 1; i <= n; i += 1) {
        suff[i].resize(m[i]);
        suff[i][m[i] - 1] = {a[i][m[i] - 1].second, m[i] - 1};
        for (int j = m[i] - 2; j >= 0; j -= 1) {
            suff[i][j] = min(suff[i][j + 1], {a[i][j].second, j}); 
        }
    }
    g.resize(sum[n] + 1);
    for (int i = 1; i <= n - 1; i += 1) {
        for (int j = 0; j < m[i]; j += 1) {
            int A = a[i][j].first;
            int B = a[i][j].second;
            int l = 0, r = m[i + 1] - 1, sol = -1;
            while (l <= r) {
                int mid = (l + r) / 2;
                if (a[i + 1][mid].first >= B) {
                    sol = mid;
                    r = mid - 1;
                } else {
                    l = mid + 1;
                }
            }
            if (sol == -1) {
                g[get_id(i + 1, suff[i + 1][0].second)].push_back(get_id(i, j));
            } else if (sol != -1) {
                g[get_id(i + 1, suff[i + 1][sol].second)].push_back(get_id(i, j));
            }
        }
    }
    dep.resize(sum[n] + 1);
    anc.assign(20, vector<int>(sum[n] + 1));
    f.assign(20, vector<int>(sum[n] + 1));
    t.assign(20, vector<ll>(sum[n] + 1));
    dfs(sum[n]);
    A.resize(sum[n] + 1);
    B.resize(sum[n] + 1);
    for (int i = 1; i <= n; i += 1) {
        for (int j = 0; j < m[i]; j += 1) {
            t[0][get_id(i, j)] = a[i][j].second - a[i][j].first; 
            A[get_id(i, j)] = a[i][j].first;
            B[get_id(i, j)] = a[i][j].second;
        }
    }
    for (int h = 1; h < 20; h += 1) {
        for (int i = 1; i <= sum[n]; i += 1) {
            anc[h][i] = anc[h - 1][anc[h - 1][i]];
        }
    }
    for (int h = 0; h < 20; h += 1) {
        for (int i = 1; i <= sum[n]; i += 1) {
            f[h][i] = get(i, (1 << h) - 1);
        }
    }
    for (int h = 1; h < 20; h += 1) {
        for (int i = 1; i <= sum[n]; i += 1) {
            int x = f[h - 1][i];
            t[h][i] = join(t[h - 1][i], t[h - 1][anc[h - 1][i]], x, anc[0][x]);
        }
    }

    // invers
    auto reva = a;
    for (int i = 1; i <= n; i += 1) {
        sort(all(reva[i]), [&](pair<int, int> a, pair<int, int> b) {
            return a.second <= b.second;
        });
    }
    vector<vector<pair<int, int>>> pref(n + 1);
    for (int i = 1; i <= n; i += 1) {
        pref[i].resize(m[i]);
        pref[i][0] = {reva[i][0].first, 0};
        for (int j = 1; j < m[i]; j += 1) {
            pref[i][j] = max(pref[i][j - 1], {reva[i][j].first, j});
        }
    }
    revg.resize(sum[n] + 1);
    for (int i = 2; i <= n - 1; i += 1) {
        for (int j = 0; j < m[i]; j += 1) {
            int A = reva[i][j].first;
            int B = reva[i][j].second;
            int l = 0, r = m[i - 1] - 1, sol = -1;
            while (l <= r) {
                int mid = (l + r) / 2;
                if (reva[i - 1][mid].second <= A) {
                    sol = mid;
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }
            if (sol == -1) {
                revg[get_id(i - 1, pref[i - 1][m[i - 1] - 1].second)].push_back(get_id(i, j));
                
            } else {
                revg[get_id(i - 1, pref[i - 1][sol].second)].push_back(get_id(i, j));
            }
        }
    }
    revanc.assign(20, vector<int>(sum[n] + 1));
    revf.assign(20, vector<int>(sum[n] + 1));
    revt.assign(20, vector<ll>(sum[n] + 1));
    RA.resize(sum[n] + 1);
    RB.resize(sum[n] + 1);
    for (int i = 1; i <= m[1]; i += 1) {
        revdfs(i);
    }
    for (int i = 1; i <= n; i += 1) {
        for (int j = 0; j < m[i]; j += 1) {
            revt[0][get_id(i, j)] = reva[i][j].second - reva[i][j].first; 
            RA[get_id(i, j)] = reva[i][j].first;
            RB[get_id(i, j)] = reva[i][j].second;
        }
    }
    for (int h = 1; h < 20; h += 1) {
        for (int i = 1; i <= sum[n]; i += 1) {
            revanc[h][i] = revanc[h - 1][revanc[h - 1][i]];
        }
    }
    for (int h = 0; h < 20; h += 1) {
        for (int i = 1; i <= sum[n]; i += 1) {
            revf[h][i] = revget(i, (1 << h) - 1);
        }
    }
    for (int h = 1; h < 20; h += 1) {
        for (int i = 1; i <= sum[n]; i += 1) {
            int x = revf[h - 1][i];
            revt[h][i] = revjoin(revt[h - 1][i], revt[h - 1][revanc[h - 1][i]], x, revanc[0][x]);
        }
    }

    vector<int> heavy;
    vector<int> id(n + 1);
    for (int i = 1; i <= n; i += 1) {
        if (m[i] >= K) {
            heavy.push_back(i);
            id[i] = heavy.size() - 1;
        }
    }
    vector<vector<ll>> ans(heavy.size(), vector<ll>(heavy.size(), 1e18));
    for (int i = 0; i < heavy.size(); i += 1) {
        for (int j = i; j < heavy.size(); j += 1) {
            int x = heavy[i];
            int y = heavy[j] + 1;
            for (int k = sum[x - 1] + 1; k <= sum[x]; k += 1) {
                ll cur = lift(k, y - x);
                ans[i][j] = min(ans[i][j], cur);
            }
        }
    }
    cin >> q;
    for (int iq = 1; iq <= q; iq += 1) {
        int l, r;
        cin >> l >> r;
        if (m[l] >= K && m[r - 1] >= K) {
            cout << ans[id[l]][id[r - 1]] << "\n";
            continue;
        }
        ll ans = 1e18;
        if (m[l] <= K) {
            for (int i = sum[l - 1] + 1; i <= sum[l]; i += 1) {
                ans = min(ans, lift(i, r - l));
            }
        } else {
            for (int i = sum[r - 2] + 1; i <= sum[r - 1]; i += 1) {
                ans = min(ans, revlift(i, r - l));
            }
        }
        cout << ans << "\n";
    }
    return 0;
}

#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...