#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, K, Q, T;
cin >> N >> K >> Q >> T;
vector<int> p1(N+1), p2(N+1);
int root1 = -1;
for(int i = 1; i <= N; i++){
cin >> p1[i];
if(p1[i] == -1) root1 = i;
}
for(int i = 1; i <= N; i++){
cin >> p2[i];
}
// Build adjacency for first tree
vector<vector<int>> adj1(N+1);
for(int i = 1; i <= N; i++){
if(p1[i] != -1){
adj1[i].push_back(p1[i]);
adj1[p1[i]].push_back(i);
}
}
// BFS to pick K connected nodes including root
vector<int> subset;
subset.reserve(K);
vector<int> parent_in_sub(N+1, -1);
vector<bool> used(N+1, false);
queue<int> q;
q.push(root1);
used[root1] = true;
subset.push_back(root1);
while(!q.empty() && subset.size() < (size_t)K){
int u = q.front(); q.pop();
for(int v: adj1[u]){
if(!used[v]){
used[v] = true;
parent_in_sub[v] = u;
subset.push_back(v);
q.push(v);
if(subset.size() == (size_t)K) break;
}
}
}
// Output chosen subset
for(int i = 0; i < K; i++) cout << subset[i] << (i+1<K?' ':'\n');
cout << flush;
// Prepare queries for edge weights
vector<pair<int,int>> queries;
queries.reserve(K-1);
for(int i = 1; i < K; i++){
int u = subset[i];
int par = parent_in_sub[u];
queries.emplace_back(par, u);
}
// Ask all queries
for(auto &pr: queries){
cout << "? " << pr.first << " " << pr.second << "\n";
}
cout << "!\n" << flush;
// Read all responses and build weighted subtrees
unordered_map<int,int> idx;
idx.reserve(K*2);
for(int i = 0; i < K; i++) idx[subset[i]] = i;
vector<vector<pair<int,ll>>> tree1(K), tree2(K);
for(auto &pr: queries){
ll d1a, d1b, d2a, d2b;
cin >> d1a >> d1b >> d2a >> d2b;
int u = pr.second;
int par = pr.first;
ll w1 = llabs(d1b - d1a);
ll w2 = llabs(d2b - d2a);
int iu = idx[u], ip = idx[par];
tree1[ip].emplace_back(iu, w1);
tree1[iu].emplace_back(ip, w1);
tree2[ip].emplace_back(iu, w2);
tree2[iu].emplace_back(ip, w2);
}
// Preprocess LCA+dist
int LOG = 1;
while((1<<LOG) <= K) LOG++;
vector<vector<int>> up1(LOG, vector<int>(K)), up2(LOG, vector<int>(K));
vector<int> depth1(K), depth2(K);
vector<ll> dist1(K), dist2(K);
function<void(int,int)> dfs1 = [&](int u, int p){
for(auto &e: tree1[u]){
int v = e.first; ll w = e.second;
if(v == p) continue;
depth1[v] = depth1[u]+1;
dist1[v] = dist1[u]+w;
up1[0][v] = u;
for(int j=1;j<LOG;j++) up1[j][v] = up1[j-1][ up1[j-1][v] ];
dfs1(v, u);
}
};
function<void(int,int)> dfs2 = [&](int u, int p){
for(auto &e: tree2[u]){
int v = e.first; ll w = e.second;
if(v == p) continue;
depth2[v] = depth2[u]+1;
dist2[v] = dist2[u]+w;
up2[0][v] = u;
for(int j=1;j<LOG;j++) up2[j][v] = up2[j-1][ up2[j-1][v] ];
dfs2(v, u);
}
};
// root at subset[0] -> index 0
for(int j=0;j<LOG;j++){ up1[j][0]=up2[j][0]=0; }
depth1[0]=depth2[0]=0;
dist1[0]=dist2[0]=0;
dfs1(0, -1);
dfs2(0, -1);
auto get_lca = [&](int u, int v, vector<int>& depth, vector<vector<int>>& up){
if(depth[u]<depth[v]) swap(u,v);
int diff = depth[u]-depth[v];
for(int j=0;j<LOG;j++) if(diff>>j &1) u=up[j][u];
if(u==v) return u;
for(int j=LOG-1;j>=0;j--){
if(up[j][u]!=up[j][v]){ u=up[j][u]; v=up[j][v]; }
}
return up[0][u];
};
// Answer T host queries
while(T--){
int pa, pb;
cin >> pa >> pb;
int ia = idx[pa], ib = idx[pb];
int c1 = get_lca(ia, ib, depth1, up1);
ll ans1 = dist1[ia] + dist1[ib] - 2*dist1[c1];
int c2 = get_lca(ia, ib, depth2, up2);
ll ans2 = dist2[ia] + dist2[ib] - 2*dist2[c2];
cout << ans1 << " " << ans2 << '\n';
}
cout << flush;
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |