Submission #906229

#TimeUsernameProblemLanguageResultExecution timeMemory
906229MilosMilutinovicPrize (CEOI22_prize)C++14
100 / 100
2980 ms991044 KiB
#include <bits/stdc++.h> using namespace std; using lint = long long; using pi = array<int, 2>; #define sz(v) ((int)(v).size()) #define all(v) (v).begin(), (v).end() const int MAX = 1000010; int n, k, q, t, r1, r2; int a[MAX], b[MAX], c[MAX], d[MAX]; vector<int> ids; namespace tree1 { int dep[MAX], logs[2 * MAX], p[MAX]; pair<int, int> st[21][2 * MAX]; vector<int> gph[MAX]; vector<pi> adj[MAX]; vector<pair<int, int>> euler; int dist[MAX]; bool seen[MAX]; void add(int u, int v) { gph[u].push_back(v); gph[v].push_back(u); } void dfs(int x, int px) { if (sz(ids) < k) { ids.push_back(x); } dep[x] = dep[px] + 1; p[x] = sz(euler); euler.push_back({dep[x], x}); for (auto& y : gph[x]) { if (y == px) continue; dfs(y, x); euler.push_back({dep[x], x}); } } int getlca(int s, int e) { if (p[s] > p[e]) swap(s, e); int k = logs[p[e] - p[s] + 1]; return min(st[k][p[s]], st[k][p[e] - (1 << k) + 1]).second; } void dfs(int x) { seen[x] = true; for (auto& y : adj[x]) { if (seen[y[0]]) continue; dist[y[0]] = dist[x] + y[1]; dfs(y[0]); } } void build() { for (int i = 2; i < 2 * MAX; i++) logs[i] = logs[i >> 1] + 1; for (int i = 0; i < sz(euler); i++) st[0][i] = euler[i]; for (int j = 1; j < 21; j++) for (int i = 0; i + (1 << j) <= sz(euler); i++) st[j][i] = min(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]); for (int i = 0; i + 1 < k; i++) { int x = ids[i]; int y = ids[i + 1]; int z = getlca(ids[i], ids[i + 1]); adj[x].push_back({z, -a[i]}); adj[z].push_back({x, a[i]}); adj[y].push_back({z, -b[i]}); adj[z].push_back({y, b[i]}); } dfs(r1); } int query(int x, int y) { return dist[x] + dist[y] - 2 * dist[getlca(x, y)]; } }; namespace tree2 { int dep[MAX], p[MAX], logs[2 * MAX]; vector<pair<int, int>> euler; pair<int, int> st[21][2 * MAX]; vector<int> gph[MAX]; vector<pi> adj[MAX]; int dist[MAX]; bool seen[MAX]; void add(int u, int v) { gph[u].push_back(v); gph[v].push_back(u); } void dfs(int x, int px) { dep[x] = dep[px] + 1; p[x] = sz(euler); euler.push_back({dep[x], x}); for (auto& y : gph[x]) { if (y == px) continue; dfs(y, x); euler.push_back({dep[x], x}); } } int getlca(int s, int e) { if (p[s] > p[e]) swap(s, e); int k = logs[p[e] - p[s] + 1]; return min(st[k][p[s]], st[k][p[e] - (1 << k) + 1]).second; } void order() { sort(all(ids), [&](int i, int j) { return p[i] < p[j]; }); } void dfs(int x) { seen[x] = true; for (auto& y : adj[x]) { if (seen[y[0]]) continue; dist[y[0]] = dist[x] + y[1]; dfs(y[0]); } } void build() { for (int i = 2; i < 2 * MAX; i++) logs[i] = logs[i >> 1] + 1; for (int i = 0; i < sz(euler); i++) st[0][i] = euler[i]; for (int j = 1; j < 21; j++) for (int i = 0; i + (1 << j) <= sz(euler); i++) st[j][i] = min(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]); for (int i = 0; i + 1 < k; i++) { int x = ids[i]; int y = ids[i + 1]; int z = getlca(ids[i], ids[i + 1]); adj[x].push_back({z, -c[i]}); adj[z].push_back({x, c[i]}); adj[y].push_back({z, -d[i]}); adj[z].push_back({y, d[i]}); } vector<int> ord(n); iota(all(ord), 0); sort(all(ord), [&](int i, int j) { return p[i] < p[j]; }); for (int x : ord) if (!seen[x]) dfs(x); } int query(int x, int y) { return dist[x] + dist[y] - 2 * dist[getlca(x, y)]; } }; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> k >> q >> t; for (int i = 0; i < n; i++) { int p; cin >> p; if (p == -1) { r1 = i; } else { --p; tree1::add(i, p); } } for (int i = 0; i < n; i++) { int p; cin >> p; if (p == -1) { r2 = i; } else { --p; tree2::add(i, p); } } tree1::dfs(r1, r1); tree2::dfs(r2, r2); tree2::order(); for (int i = 0; i < k; i++) { cout << ids[i] + 1 << " "; } cout << "\n"; for (int i = 0; i + 1 < k; i++) { cout << "? " << ids[i] + 1 << " " << ids[i + 1] + 1 << "\n"; } cout << "!" << endl; for (int i = 0; i + 1 < k; i++) { cin >> a[i] >> b[i] >> c[i] >> d[i]; } tree1::build(); tree2::build(); vector<int> x(t), y(t); for (int i = 0; i < t; i++) { cin >> x[i] >> y[i]; --x[i]; --y[i]; } for (int i = 0; i < t; i++) { cout << tree1::query(x[i], y[i]) << " " << tree2::query(x[i], y[i]) << "\n"; } cout << endl; }
#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...