-
Notifications
You must be signed in to change notification settings - Fork 0
/
12238-Ants-Colony-DS.cpp
96 lines (80 loc) · 2.37 KB
/
12238-Ants-Colony-DS.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* Author: Francisco Soulignac (modificado levemente por Dario y Nicolas)
* Time in UVA: 0.31
*/
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
class LCA {
struct Query {
int v, idx;
};
//pos[v] primera aparicion de v en un recorrido
//dist[i] = distancia del vertice que se recorre en el i-esimo paso del DFS a la raiz (lo necesario para RMQ)
vector<int> pos, uf;
vector<ll> dist;
vector<vector<Query>> rmqs;
int qsize = 0;
//calcula la info para el rmq; notar que el arbol ya lo tenemos
void dfs(const vector<vector<int>>& c, const vector<ll>& d, int v) {
pos[v] = dist.size();
dist.push_back(d[v]);
for(auto w: c[v]) {
dfs(c, d, w);
dist.push_back(d[v]);
}
}
int find(int v) {
return uf[v] == -1 ? v : uf[v] = find(uf[v]);
}
public:
LCA(const vector<ll>& d, const vector<vector<int>>& c) : pos(d.size()), rmqs(2*d.size()), qsize(0) {
dfs(c, d, 0);
}
void add_query(int v, int w) {
if(pos[v] > pos[w]) swap(v, w);
rmqs[pos[w]].push_back({pos[v], qsize++});
}
vector<ll> answers() {
uf.assign(dist.size(), -1);
vector<int> roots;
vector<ll> res(qsize);
for(int to = 0; to < dist.size(); ++to) {
while(not roots.empty() and dist[roots.back()] > dist[to]) {
uf[roots.back()] = to;
roots.pop_back();
}
roots.push_back(to);
for(auto q: rmqs[to]) {
res[q.idx] = dist[q.v] + dist[to] - 2*dist[find(q.v)];
}
}
return res;
}
};
int main() {
ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
int n, q;
while(cin >> n and n) {
//d = distancia a la raiz
vector<ll> d(n, 0);
vector<vector<int>> T(n);
for(int v = 1; v < n; ++v) {
int u; ll l;
cin >> u >> l;
d[v] = d[u] + l;
T[u].push_back(v);
}
LCA lca(d, T);
cin >> q;
while(q--) {
int v, w;
cin >> v >> w;
lca.add_query(v, w);
}
auto ds = lca.answers();
for(int i = 0; i+1 < ds.size(); ++i) cout << ds[i] << ' ';
if(not ds.empty()) cout << ds.back();
cout << '\n';
}
}