forked from mpfeifer1/Kattis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstogovi.cpp
129 lines (108 loc) · 2.58 KB
/
stogovi.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <bits/stdc++.h>
using namespace std;
vector<vector<int> > adj, memo;
vector<int> depth, parent, conv;
vector<bool> visited;
int LOG = 21;
// Calculate depth for all nodes
void dfs(int node, int Depth = 0) {
depth[node] = Depth;
for(int x : adj[node]) {
dfs(x, Depth+1);
}
}
// Find LCA of two nodes (O(log(n))
int lca(int x, int y) {
if(depth[x] < depth[y]) swap(x,y);
int diff = depth[x] - depth[y];
for(int k = LOG; k >= 0; --k) {
if(diff&(1<<k)) {
x = memo[x][k];
}
}
for(int k = LOG; k >= 0; --k) {
if(memo[x][k] != memo[y][k]) {
x = memo[x][k];
y = memo[y][k];
}
}
if(x != y) x = parent[x];
return x;
}
// Define query struct
struct query {
char c;
int v, w;
};
int main() {
// Fast IO
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
// Read in N
int n;
cin >> n;
// Allocate storage
// One based labeling for nodes.
adj.resize(n+1);
conv.resize(n+1);
depth.resize(n+1);
parent.resize(n+1);
vector<query> queries(n+1);
// Read in all connections
for(int i = 1; i <= n; ++i) {
// Read in type
char c;
cin >> c;
queries[i].c = c;
// Read in first number
int v;
cin >> v;
v = conv[v];
queries[i].v = v;
if(c == 'a') {
// Create new node
parent[i] = v;
adj[v].push_back(i);
// Set this node to be itself
conv[i] = i;
}
if(c == 'b') {
// Set this node to be the parent of the node
conv[i] = parent[v];
}
if(c == 'c') {
// Read in compare node
int w;
cin >> w;
w = conv[w];
queries[i].w = w;
// Set this node to be the node
conv[i] = v;
}
}
// DFS
parent[0] = 0;
dfs(0);
// Calculate LCA table
memo.resize(n+1, vector<int>(LOG+1,0));
for(int i = 1; i <= n; ++i) memo[i][0] = parent[i];
for(int k = 1; k <= LOG; ++k) {
for(int i = 1; i <= n; ++i) {
memo[i][k] = memo[memo[i][k-1]][k-1];
}
}
// Run through all queries and print answers
for(int i = 1; i <= n; i++) {
int c = queries[i].c;
int v = queries[i].v;
int w = queries[i].w;
if(c == 'b') {
cout << v << endl;
}
if(c == 'c') {
int node = lca(v, w);
cout << depth[conv[node]] << endl;
}
}
return 0;
}