Submission #1171641

#TimeUsernameProblemLanguageResultExecution timeMemory
1171641Perl32Tourism (JOI23_tourism)C++20
100 / 100
594 ms55572 KiB
//I wrote this code 4 u <3
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

const int inf = 0x3f3f3f3f;

struct Info {
    int dep = inf, i = -1;

    Info() = default;
    Info(int _dep, int _i) : dep(_dep), i(_i) {}
};

Info operator+(const Info& a, const Info& b) {
    Info res;
    if (a.dep < b.dep) res = a;
    else res = b;
    return res;
}

struct SPT {
    vector<vector<Info>> mat;

    SPT(vector<Info>& a) {
        int n = (int) a.size();
        const int max_log = 32 - __builtin_clz(n);
        mat.resize(max_log);
        mat[0] = a;
        for (int i = 1; i < max_log; ++i) {
            const int l = (1 << i), h = (1 << (i - 1));
            mat[i].resize(n - l + 1);
            for (int j = 0; j < n - l + 1; ++j) {
                mat[i][j] = mat[i - 1][j] + mat[i - 1][j + h];
            }
        }
    }

    Info get(int l, int r) {
        int lvl = 31 - __builtin_clz(r - l + 1);
        return mat[lvl][l] + mat[lvl][r - (1 << lvl) + 1];
    }
};

struct BIT {
    vector<int> t, tm;
    int n, T;

    BIT(int _n) : t(_n + 1), tm(_n + 1, -1), n(_n), T(0) {}

    void extend() { T++; }

    void upd(int i, int v) {
        for (++i; i <= n; i += i & -i) {
            if (tm[i] == T) {
                t[i] += v;
            } else {
                t[i] = v;
                tm[i] = T;
            }
        }
    }

    int get(int r) {
        int res = 0;
        for (; r; r -= r & -r) {
            if (tm[r] == T) res += t[r];
        }
        return res;
    }
};

signed main(int32_t argc, char *argv[]) {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m, q;
    cin >> n >> m >> q;
    vector<vector<int>> tree(n);
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        --u, --v;
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    vector<Info> euler;
    vector<int> tin(n), tout(n), dep(n);
    auto Dfs1 = [&](auto&& self, int u, int p) -> void {
        tin[u] = (int) euler.size();
        euler.emplace_back(dep[u], u);
        for (auto to : tree[u]) {
            if (to == p) continue;
            dep[to] = dep[u] + 1;
            self(self, to, u);
            euler.emplace_back(dep[u], u);
        }
        tout[u] = (int) euler.size();
    };
    dep[0] = 0;
    Dfs1(Dfs1, 0, -1);
    SPT spt(euler);
    auto lca = [&](int u, int v) {
        if (tin[u] > tin[v]) swap(u, v);
        return spt.get(tin[u], tin[v]).i;
    };
    auto isp = [&](int u, int v) { return tin[u] <= tin[v] && tout[v] <= tout[u]; };
    vector<int> a(m);
    for (auto& x : a) {
        cin >> x; --x;
    }
    vector<array<int, 2>> qq(q);
    for (auto& [lx, rx] : qq) {
        cin >> lx >> rx;
        --lx, --rx;
    }
    int T = 0;
    vector<vector<pair<int, int>>> g(n);
    auto add_edge = [&](int u, int v, int w) {
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    };
    vector<array<int, 3>> adj;
    vector<int> ans(q, 1), tm(n, -1), lft(n), rig(n);
    auto Dfs2 = [&](auto&& self, int u, int p) -> void {
        if (tm[u] != T) {
            lft[u] = -1; rig[u] = m;
        }
        for (auto [to, w] : g[u]) {
            if (to == p) continue;
            self(self, to, u);
            lft[u] = max(lft[u], lft[to]);
            rig[u] = min(rig[u], rig[to]);
            adj.push_back({lft[to], rig[to], w});
        }
    };
    BIT tt(m + 1);
    auto divi = [&](auto&& self, int lx, int rx, vector<int>& ord) {
        if (lx >= rx) return;
        int mid = (lx + rx) >> 1;
        vector<int> lb, rb, nw;
        for (auto i : ord) {
            auto [ql, qr] = qq[i];
            if (ql <= mid && qr > mid) {
                nw.push_back(i);
            } else if (qr <= mid) {
                lb.push_back(i);
            } else if (ql > mid) {
                rb.push_back(i);
            }
        }
        self(self, lx, mid, lb);
        self(self, mid + 1, rx, rb);
        T++;
        vector<int> aboba;
        for (int i = lx; i <= rx; ++i) {
            int v = a[i];
            if (tm[v] != T) {
                aboba.push_back(v);
                g[v].clear();
                if (i <= mid) {
                    lft[v] = i;
                    rig[v] = m;
                } else {
                    rig[v] = i;
                    lft[v] = -1;
                }
                tm[v] = T;
            }
            if (i <= mid) lft[v] = max(lft[v], i);
            if (i > mid) rig[v] = min(rig[v], i);
        }
        sort(aboba.begin(), aboba.end(), [&](int u, int v) { return tin[u] < tin[v]; });
        int sz = (int) aboba.size();
        for (int i = 0; i + 1 < sz; ++i) aboba.push_back(lca(aboba[i], aboba[i + 1]));
        sort(aboba.begin(), aboba.end(), [&](int u, int v) { return tin[u] < tin[v]; });
        aboba.resize(unique(aboba.begin(), aboba.end()) - aboba.begin());
        sz = (int) aboba.size();
        vector<int> st;
        for (auto u : aboba) {
            if (tm[u] != T) g[u].clear();
            while (!st.empty() && !isp(st.back(), u)) st.pop_back();
            if (!st.empty()) add_edge(st.back(), u, dep[u] - dep[st.back()]);
            st.push_back(u);
        }
        adj.clear();
        Dfs2(Dfs2, a[mid], -1);
        sort(nw.begin(), nw.end(), [&](int i, int j) { return qq[i] > qq[j]; });
        sort(adj.rbegin(), adj.rend());
        int r = 0;
        tt.extend();
        for (auto i : nw) {
            auto [ql, qr] = qq[i];
            while (r < (int) adj.size() && adj[r][0] >= ql) { tt.upd(adj[r][1], adj[r][2]); r++; }
            ans[i] += tt.get(m + 1) - tt.get(qr + 1);
        }
        while (r < (int) adj.size()) { tt.upd(adj[r][1], adj[r][2]); r++; }
        for (auto i : nw) {
            auto [ql, qr] = qq[i];
            ans[i] += tt.get(qr + 1);
        }
    };
    vector<int> ord(q);
    iota(ord.begin(), ord.end(), 0);
    divi(divi, 0, m - 1, ord);
    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...