結果
| 問題 | No.3442 Good Vertex Connectivity |
| コンテスト | |
| ユーザー |
👑 potato167
|
| 提出日時 | 2026-01-04 16:32:12 |
| 言語 | C++17 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 833 ms / 3,000 ms |
| コード長 | 5,982 bytes |
| 記録 | |
| コンパイル時間 | 2,851 ms |
| コンパイル使用メモリ | 234,480 KB |
| 実行使用メモリ | 42,220 KB |
| 最終ジャッジ日時 | 2026-02-06 20:52:24 |
| 合計ジャッジ時間 | 44,463 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 69 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#include <atcoder/segtree>
namespace po167{
template<class T, T(*op)(T, T)>
struct Sparse_table{
int n;
int depth;
std::vector<std::vector<T>> val;
void init(std::vector<T> &v){
depth = 1;
n = v.size();
while ((1 << depth) <= n) depth++;
val.resize(depth);
val[0] = v;
for (int i = 1; i < depth; i++){
val[i].resize(n);
for (int j = 0; j <= n - (1 << i); j++){
val[i][j] = op(val[i - 1][j], val[i - 1][j + (1 << (i - 1))]);
}
}
}
Sparse_table(std::vector<T> v){
init(v);
}
Sparse_table(){}
// 0 <= l < r <= n
// if l == r : assert
T prod(int l, int r){
assert(0 <= l && l < r && r <= n);
int z=31-__builtin_clz(r-l);
return op(val[z][l], val[z][r - (1 << z)]);
}
};
}
namespace po167{
int op(int a, int b){
return std::min(a, b);
}
struct LCA{
Sparse_table<int, op> table;
std::vector<int> depth;
std::vector<int> E;
std::vector<int> order;
int var_num;
void init(std::vector<std::vector<int>> &g, int root = 0){
var_num = g.size();
assert(0 <= root && root < var_num);
std::vector<int> val;
depth.assign(var_num, -1);
depth[root] = 0;
E.resize(var_num);
std::vector<int> tmp;
order.clear();
tmp.reserve(var_num);
order.reserve(var_num);
int c = 0;
auto dfs = [&](auto self, int var, int pare) -> void {
E[var] = c++;
if (var != root) tmp.push_back(E[pare]);
order.push_back(var);
for (auto x : g[var]) if (depth[x] == -1){
depth[x] = depth[var] + 1;
self(self, x, var);
}
};
dfs(dfs, root, -1);
assert(c == var_num);
table.init(tmp);
}
void init(std::vector<int> &pare){
int root = -1;
int n = pare.size();
std::vector<std::vector<int>> g(n);
for (int i = 0; i < n; i++){
if (pare[i] < 0){
assert(root == -1);
root = i;
}
else{
assert(0 <= pare[i] && pare[i] < n);
g[pare[i]].push_back(i);
}
}
assert(root != -1);
init(g, root);
}
LCA (std::vector<std::vector<int>> g, int root = 0){
init(g, root);
}
LCA (std::vector<int> pare){
init(pare);
}
LCA(){
}
int lca(int a, int b){
assert(0 <= std::min(a, b) && std::max(a, b) < var_num);
if (a == b) return a;
if (E[a] > E[b]) std::swap(a, b);
return order[table.prod(E[a], E[b])];
}
int dist(int a, int b){
assert(0 <= std::min(a, b) && std::max(a, b) < var_num);
return depth[a] + depth[b] - 2 * depth[lca(a, b)];
}
int back(int var, int len){
assert(len <= depth[var]);
if (len == 0) return var;
int l = 0, r = E[var];
while (r - l > 1){
int m = (l + r) / 2;
if (depth[var] - depth[order[table.prod(m, E[var])]] < len){
r = m;
}
else l = m;
}
return order[table.prod(l, E[var])];
}
// a -> b
int jump(int a, int b, int len){
int c = lca(a, b);
if (len <= depth[a] - depth[c]) return back(a, len);
len -= depth[a] - depth[c];
if (len <= depth[b] - depth[c]) return back(b, depth[b] - depth[c] - len);
return -1;
}
};
}
po167::LCA lca;
struct F{
int l = -1;
int r = -1;
int ans = 0;
};
F op(F l, F r){
if (l.l == -1) return r;
if (r.r == -1) return l;
l.ans += r.ans;
l.ans += lca.dist(l.r, r.l);
l.r = r.r;
return l;
}
F e(){
return F{};
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int N;
cin >> N;
vector<vector<int>> G(N);
for (int i = 0; i < N - 1; i++){
int a, b;
cin >> a >> b;
a--, b--;
G[a].push_back(b);
G[b].push_back(a);
}
lca.init(G);
vector<int> L(N), R(N);
{
int tmp = 0;
auto dfs = [&](auto self, int var, int par) -> void {
L[var] = tmp;
tmp++;
for (auto x : G[var]) if (x != par){
self(self, x, var);
}
R[var] = tmp;
};
dfs(dfs, 0, -1);
}
vector<int> p(N);
atcoder::segtree<F, op, e> seg(N);
for (int i = 0; i < N; i++){
cin >> p[i];
if (p[i]){
seg.set(L[i], {i, i, 0});
}
}
int Q;
cin >> Q;
while (Q--){
int t;
cin >> t;
// 変更クエリ
if (t == 1){
int var;
cin >> var;
var--;
p[var] ^= 1;
if (p[var]){
seg.set(L[var], {var, var, 0});
}
else{
seg.set(L[var], e());
}
}
// 出力クエリ
if (t == 2){
int x, y;
cin >> x >> y;
x--, y--;
F tmp;
// x == y のとき
if (x == y){
tmp = seg.all_prod();
}
// y の部分木内に x が存在するとき
else if (L[y] < L[x] && L[x] < R[y]){
// x から y へ行き、その 1 つ前の頂点を考える
int z = lca.jump(y, x, 1);
tmp = op(seg.prod(0, L[z]), seg.prod(R[z], N));
}
// そうでないとき
else{
tmp = seg.prod(L[y], R[y]);
}
if (tmp.l == -1){
tmp.ans = -2;
}
else{
tmp.ans += lca.dist(tmp.l, tmp.r);
}
cout << 1 + tmp.ans / 2 << "\n";
}
}
}
potato167