結果
| 問題 |
No.3189 Semifinal Stage
|
| コンテスト | |
| ユーザー |
Rubikun
|
| 提出日時 | 2025-06-20 22:48:00 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,114 ms / 4,000 ms |
| コード長 | 4,103 bytes |
| コンパイル時間 | 2,701 ms |
| コンパイル使用メモリ | 218,132 KB |
| 実行使用メモリ | 62,452 KB |
| 最終ジャッジ日時 | 2025-06-20 22:48:27 |
| 合計ジャッジ時間 | 22,723 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 30 |
ソースコード
// https://ferin-tech.hatenablog.com/entry/2020/03/06/162311
// https://ideone.com/QhYs5x
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<ll, ll>;
#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
template<typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template<typename T> void chmax(T &a, const T &b) { a = max(a, b); }
struct FastIO {FastIO() { cin.tie(0); ios::sync_with_stdio(0); }}fastiofastio;
#ifdef DEBUG_
#include "../program_contest_library/memo/dump.hpp"
#else
#define dump(...)
#endif
const ll INF = 1LL<<60;
struct LCA {
const int n = 0;
const int log2_n = 0;
vector<vector<int>> g;
vector<vector<int>> par; // par[2^i上][頂点v]
vector<int> dep;
void dfs(int v, int p, int d) {
par[0][v] = p;
dep[v] = d;
for(auto to: g[v]) {
if(to == p) continue;
dfs(to, v, d+1);
}
}
LCA() {}
LCA(int n) : n(n), log2_n(log2(n)+1), g(n),
par(log2_n, vector<int>(n)), dep(n) {}
void add_edge(int u, int v) {
g[u].push_back(v);
g[v].push_back(u);
}
void build(ll root=0) {
dfs(root, -1, 0);
for(int i=0; i+1 < log2_n; ++i) {
for(int j = 0; j < n; ++j) {
if(par[i][j] < 0) par[i+1][j] = -1;
else par[i+1][j] = par[i][par[i][j]];
}
}
}
int get(int u, int v) {
if(dep[u] > dep[v]) swap(u, v);
REP(i, log2_n) {
if((dep[v] - dep[u]) >> i & 1) {
v = par[i][v];
}
}
if(u == v) return u;
for(int i=log2_n-1; i>=0; --i) {
if(par[i][u] != par[i][v]) {
u = par[i][u];
v = par[i][v];
}
}
return par[0][u];
}
ll dist(ll u, ll v) {
return dep[u] + dep[v] - 2 * dep[get(u, v)];
}
};
int main(void) {
ll n;
cin >> n;
LCA lca(n);
vector<vector<ll>> g(n);
REP(i, n-1) {
ll a, b;
cin >> a >> b;
a--, b--;
g[a].push_back(b);
g[b].push_back(a);
lca.add_edge(a, b);
}
lca.build();
vector<ll> sz(n), dead(n);
auto find_centroid = [&](ll root) {
auto get_size = [&](auto &&self, ll v, ll p) -> void {
sz[v] = 1;
for(auto to: g[v]) if(to != p && !dead[to]) {
self(self, to, v);
sz[v] += sz[to];
}
};
get_size(get_size, root, -1);
auto dfs = [&](auto &&self, ll v, ll p) -> ll {
for(auto to: g[v]) if(to != p && !dead[to]) {
if(sz[to] > sz[root]/2) return self(self, to, v);
}
return v;
};
return dfs(dfs, root, -1);
};
vector<ll> par(n);
auto centroid_decomposition = [&](auto &&self, ll root, ll p) -> void {
ll c = find_centroid(root);
dead[c] = true;
par[c] = p;
for(auto to: g[c]) if(!dead[to]) {
self(self, to, c);
}
dead[c] = false;
};
centroid_decomposition(centroid_decomposition, 0, -1);
vector<ll> col(n);
vector<set<PII>> dist_to_white(n);
auto paint = [&](ll v) {
ll u = v;
while(u != -1) {
if(col[v] == 0) dist_to_white[u].insert({lca.dist(u, v), v});
else dist_to_white[u].erase({lca.dist(u, v), v});
u = par[u];
}
col[v] = 1-col[v];
};
auto query = [&](ll v) {
ll u = v, ret = INF;
while(u != -1) {
if(dist_to_white[u].size()) {
chmin(ret, dist_to_white[u].begin()->first + lca.dist(u, v));
}
u = par[u];
}
return ret == INF ? -1 : ret;
};
ll q;
cin >> q;
REP(i, q) {
ll t, v;
cin >> t >> v;
v--;
if(t == 1) paint(v);
else cout << query(v) << "\n";
}
cout << flush;
return 0;
}
Rubikun