Submission #1235341

#TimeUsernameProblemLanguageResultExecution timeMemory
1235341spetrPrize (CEOI22_prize)C++20
0 / 100
3587 ms1071076 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int MAXN = 1000000;
int n, k, q, t;
int p1[MAXN], p2[MAXN];
vector<int> tree1[MAXN], tree2[MAXN];

int dfn[MAXN], inv_dfn[MAXN], dfc;
int sz[MAXN], parent1[MAXN], depth1[MAXN], heavy[MAXN];
int head1[MAXN];

ll dist1[MAXN];
ll dis_query[MAXN];

// HLD on tree1
int dfs_sz(int u) {
    sz[u] = 1;
    int maxsz = 0;
    for (int v : tree1[u]) {
        depth1[v] = depth1[u] + 1;
        parent1[v] = u;
        ll w = 0; // we don't know weights here
        dist1[v] = dist1[u] + w;
        int vsz = dfs_sz(v);
        sz[u] += vsz;
        if (vsz > maxsz) {
            maxsz = vsz;
            heavy[u] = v;
        }
    }
    return sz[u];
}

void dfs_hld(int u, int h) {
    head1[u] = h;
    dfn[u] = dfc;
    inv_dfn[dfc++] = u;
    if (heavy[u] != -1) dfs_hld(heavy[u], h);
    for (int v : tree1[u]) if (v != heavy[u]) {
        dfs_hld(v, v);
    }
}

int lca1(int u, int v) {
    while (head1[u] != head1[v]) {
        if (depth1[head1[u]] > depth1[head1[v]]) u = parent1[head1[u]];
        else v = parent1[head1[v]];
    }
    return depth1[u] < depth1[v] ? u : v;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> k >> q >> t;
    int root = -1;
    for(int i = 0; i < n; i++){
        cin >> p1[i];
        if(p1[i] == -1) root = i;
        else tree1[p1[i]].push_back(i);
    }
    for(int i = 0; i < n; i++){
        cin >> p2[i];
        if(p2[i] != -1) tree2[p2[i]].push_back(i);
    }
    // init
    fill(heavy, heavy+n, -1);
    parent1[root] = root;
    depth1[root] = 0;
    dist1[root] = 0;
    dfs_sz(root);
    dfs_hld(root, root);

    // choose first k by dfn order
    vector<int> subset(k);
    for(int i = 0; i < k; i++) subset[i] = inv_dfn[i];

    // output subset
    for(int i = 0; i < k; i++) cout << subset[i]+1 << (i+1<k?' ':'\n');
    // queries for each except root
    for(int i = 1; i < k; i++) {
        cout << "? " << subset[0]+1 << " " << subset[i]+1 << "\n";
    }
    cout << "!\n" << flush;

    // read q responses: format d1(root,a), d1(root,a), d2(root,a), d2(root,a)
    for(int i = 1; i < k; i++){
        ll d1l, d1a, d2l, d2a;
        cin >> d1l >> d1a >> d2l >> d2a;
        dis_query[ subset[i] ] = d1a;
        // store second tree same for simplicity
        dis_query[ subset[i]+n ] = d2a;
    }
    dis_query[ subset[0] ] = 0;
    dis_query[ subset[0]+n ] = 0;

    // answer t queries
    while(t--) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        // tree1 distance
        int w = lca1(u, v);
        ll d1 = dis_query[u] + dis_query[v] - 2*dis_query[w];
        // tree2 uses same lca
        ll d2 = dis_query[u+n] + dis_query[v+n] - 2*dis_query[w+n];
        cout << d1 << " " << d2 << '\n';
    }
    cout << flush;
    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...