Submission #1222681

#TimeUsernameProblemLanguageResultExecution timeMemory
1222681omsincoconutPrize (CEOI22_prize)C++17
100 / 100
1262 ms331868 KiB
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int N, K, Q, T;

struct MinSegtree{
    int n;
    vector<pair<int, int>> tree;

    void init(vector<pair<int, int>> val) {
        n = val.size();
        tree = vector<pair<int, int>>(2*n, {INT_MAX, INT_MAX});
        for (int i = 0; i < n; i++) tree[n+i] = val[i];
        for (int i = n-1; i >= 1; i--) tree[i] = min(tree[i<<1], tree[(i<<1)|1]);
    }

    pair<int, int> query(int l, int r) {
        r++;
        pair<int, int> ret = {INT_MAX, INT_MAX};
        for (l += n, r += n; l < r; l>>=1, r>>=1) {
            if (l&1) ret = min(ret, tree[l++]);
            if (r&1) ret = min(ret, tree[--r]);
        }
        return ret;
    }
};

struct Tree{
    int n, root;
    vector<int> p;
    vector<vector<int>> child;

    vector<int> tin, depth, ord;
    MinSegtree segtree;

    int cte = -1;
    void gen_ett(int u) {
        tin[u] = ++cte;
        ord.push_back(u);

        for (int v : child[u]) {
            depth[v] = depth[u]+1;
            gen_ett(v);
            ++cte;
            ord.push_back(u);
        }
    }

    void readtree(int _n) {
        n = _n;
        p = tin = depth = vector<int>(n);
        child = vector<vector<int>>(n);

        for (int i = 0; i < n; i++) {
            cin >> p[i];
            if (p[i] == -1) root = i;
            else {
                p[i]--; // Change 1-based index to 0-based index
                child[p[i]].push_back(i);
            }
        }

        depth[root] = 0;
        gen_ett(root);

        vector<pair<int, int>> tmp(ord.size());
        for (int i = 0; i < ord.size(); i++)
            tmp[i] = make_pair(depth[ord[i]], ord[i]);

        segtree.init(tmp);
    }

    vector<int> sort_by_tin(vector<int> x) {
        sort(x.begin(), x.end(), [this](int a, int b) {
            return tin[a] < tin[b];
        });
        return x;
    }

    int lca(int u, int v) {
        return segtree.query(min(tin[u], tin[v]), max(tin[u], tin[v])).second;
    }
} tree1, tree2;

struct EqSolver{
    int n;
    vector<vector<pair<int, ll>>> edge;
    vector<ll> result;

    void init(int _n, vector<int> a, vector<int> b, vector<ll> c, int root) {
        n = _n;
        edge = vector<vector<pair<int, ll>>>(n);
        result = vector<ll>(n);

        for (int i = 0; i < a.size(); i++) {
            edge[a[i]].emplace_back(b[i], -c[i]);
            edge[b[i]].emplace_back(a[i], c[i]);
        }

        vector<bool> vis(n);
        queue<int> bfs;
        bfs.push(root);

        while (!bfs.empty()) {
            int u = bfs.front();
            bfs.pop();
            if (vis[u]) continue;
            vis[u] = true;

            for (auto [v, w] : edge[u]) {
                if (!vis[v]) {
                    result[v] = result[u]+w;
                    bfs.push(v);
                } 
            }
        }
    }
} solver1, solver2;

pair<vector<array<int, 4>>, vector<pair<int, int>>> query(vector<int> x, vector<int> u, vector<int> v) {
    for (int i : x)
        cout << i+1 << " "; // Change 0-based index to 1-based index
    cout << endl;

    int q = u.size();

    for (int i = 0; i < q; i++)
        cout << "? " << u[i]+1 << " " << v[i]+1 << "\n"; // Change 0-based index to 1-based index
    cout << "!" << endl;

    vector<array<int, 4>> ret1(q);
    for (int i = 0; i < q; i++) cin >> ret1[i][0] >> ret1[i][1] >> ret1[i][2] >> ret1[i][3];

    vector<pair<int, int>> ret2(T);
    for (int i = 0; i < T; i++) {
        cin >> ret2[i].first >> ret2[i].second;
        ret2[i].first--; ret2[i].second--; // Change 1-based index to 0-based index
    }

    return make_pair(ret1, ret2);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> N >> K >> Q >> T;
    tree1.readtree(N);
    tree2.readtree(N);

    vector<int> x(N);
    iota(x.begin(), x.end(), 0);
    x = tree1.sort_by_tin(x);
    x.resize(K);
    x = tree2.sort_by_tin(x);

    vector<int> u(K-1), v(K-1);
    for (int i = 0; i < K-1; i++) u[i] = x[i], v[i] = x[i+1];
    
    auto [query_results, questions] = query(x, u, v);

    // Create solver1
    {
        vector<int> a(2*(K-1)), b(2*(K-1));
        vector<ll> c(2*(K-1));
        for (int i = 0; i < K-1; i++) {
            int lca_node = tree1.lca(u[i], v[i]);
            a[2*i] = u[i];
            b[2*i] = lca_node;
            c[2*i] = query_results[i][0];
            a[2*i+1] = v[i];
            b[2*i+1] = lca_node;
            c[2*i+1] = query_results[i][1];
        }

        solver1.init(N, a, b, c, u[0]);
    }

    // Create solver2
    {
        vector<int> a(2*(K-1)), b(2*(K-1));
        vector<ll> c(2*(K-1));
        for (int i = 0; i < K-1; i++) {
            int lca_node = tree2.lca(u[i], v[i]);
            a[2*i] = u[i];
            b[2*i] = lca_node;
            c[2*i] = query_results[i][2];
            a[2*i+1] = v[i];
            b[2*i+1] = lca_node;
            c[2*i+1] = query_results[i][3];
        }

        solver2.init(N, a, b, c, u[0]);
    }

    for (auto [a, b] : questions) {
        ll ans1 = solver1.result[a] + solver1.result[b] - 2*solver1.result[tree1.lca(a, b)];
        ll ans2 = solver2.result[a] + solver2.result[b] - 2*solver2.result[tree2.lca(a, b)];
        cout << ans1 << " " << ans2 << "\n";
    }
    cout << endl;

    return 0;
}

/*
9 3 2 3
2 -1 2 1 1 5 1 4 5
9 4 5 5 7 3 -1 3 7
*/

/*
10 0 0 1
0 3 13 5
4 2
4 1
1 2
*/
#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...