我觉得这个题就是求 树上一个点集的 直径,所以我觉得似乎可以选择 离重心最远的一个点 开始点分树的暴力跳父亲。
但是只过 hack,求问这样做可不可行。不可行能不能给个小数据把代码 hack 了。
Code:
#include <bits/stdc++.h>
using namespace std;
using LL = __int128;
using ll = long long;
using ldb = long double;
using vi = vector < int >;
#define ve vector < edge >
#define pb(x) emplace_back(x)
#define lowbit(x) ((x) & -(x))
#define me(a, b) memset(a, b, sizeof(a));
#define L(i, j, k) for (int i = j; i <= int(k); i++)
#define R(i, j, k) for (int i = j; i >= int(k); i--)
#define debug cerr << __FILE__ << ": " << __LINE__ << '\n';
#define qio() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
const int N = 1e5 + 5; // Adjust
const int LG = 19;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int read() {
int res(0);
char ch(getchar());
while (ch < '0' || ch > '9')
ch = getchar();
while (ch >= '0' && ch <= '9') {
res = res * 10 + (ch ^ '0');
ch = getchar();
}
return res;
}
struct edge {
int v, w;
};
struct vertex { // 这个东西放到优先队列里,用来求离重心最远的点
int u, dep;
inline bool operator < (const vertex& x) const {
return dep < x.dep;
}
inline bool operator == (const vertex& x) const {
return u == x.u && dep == x.dep;
}
inline void operator += (const vertex& x) const {
// 只用于避免编译错误
}
inline bool operator <= (const vertex& x) const {
return *this < x | *this == x;
}
};
template < class T >
struct deletable_heap { // 可删堆
#define DEL 1
#define USE 0
priority_queue < T > Q[2];
inline void push(T x) {
Q[USE].push(x);
}
inline void remove(T x) {
Q[DEL].push(x);
}
inline void pop() {
Q[USE].pop();
}
inline T top() {
while (!Q[DEL].empty() && !Q[USE].empty() && Q[USE].top() <= Q[DEL].top()) {
Q[USE].pop();
Q[DEL].pop();
}
return Q[USE].top();
}
inline int size() {
return Q[USE].size() - Q[DEL].size();
}
inline T exact_pop() {
return Q[USE].top();
}
inline T sum2() { // top + sectop
T ret = Q[USE].top(), tmp = ret;
Q[USE].pop();
ret += top();
push(tmp);
return ret;
}
};
int n, dist[N];
ve G[N];
bool sit[N];
namespace LCA { // 计算点之间的距离
int cnt(0), dfn[N], dep[N], rmq[LG][N];
inline int get(int a, int b) {
return dfn[a] < dfn[b] ? a : b;
}
void dfs(int u, int fa) {
rmq[0][dfn[u] = ++cnt] = fa;
for (edge e : G[u])
if (e.v != fa) {
dep[e.v] = dep[u] + e.w;
dfs(e.v, u);
}
}
void init() {
dfs(1, 0);
L(i, 1, __lg(n))
L(j, 1, n + 1 - (1 << i))
rmq[i][j] = get(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
}
inline int lca(int u, int v) {
if (u == v)
return v;
if ((u = dfn[u]) > (v = dfn[v]))
swap(u, v);
int d = __lg(v - u++);
return get(rmq[d][u], rmq[d][v - (1 << d) + 1]);
}
inline int dis(int u, int v) {
int l = lca(u, v);
return dep[u] + dep[v] - 2 * dep[l];
}
} using LCA::dis;
namespace DCT {
deletable_heap < int > A[N], B[N], C;
int rt, sum, sz[N], f[N], rf[N];
bool vis[N];
void centroid(int u, int fa) {
sz[u] = 1;
f[u] = 0;
for (edge e : G[u])
if (e.v != fa && !vis[e.v]) {
centroid(e.v, u);
sz[u] += sz[e.v];
f[u] = max(f[u], sz[e.v]);
}
f[u] = max(f[u], sum - sz[u]);
if (f[u] < f[rt])
rt = u;
}
void rebuild(int u, int fa) { // 重构
vis[u] = 1;
sz[u] = sum + 1;
int v;
for (edge e : G[u]) {
v = e.v;
if (v != fa && !vis[v]) {
sum = sz[v];
rt = 0;
centroid(v, u);
centroid(rt, 0);
rf[rt] = u;
rebuild(rt, u);
}
}
}
void init() { // 在询问及修改开始前对点进行初始化
L(u, 1, n)
for (int i = u; rf[i]; i = rf[i])
A[i].push(dis(u, rf[i]));
L(i, 1, n)
B[rf[i]].push(A[i].top());
}
void off(int u) { // 关灯
for (int i = u; rf[i]; i = rf[i]) {
// C.remove(B[rf[i]].sum2());
B[rf[i]].remove(A[i].top());
A[i].push(dis(u, rf[i]));
B[rf[i]].push(A[i].top());
// C.push(B[rf[i]].sum2());
}
}
void light(int u) { // 开灯
for (int i = u; rf[i]; i = rf[i]) {
// C.remove(B[rf[i]].sum2());
B[rf[i]].remove(A[i].top());
A[i].remove(dis(u, rf[i]));
B[rf[i]].push(A[i].top());
// C.push(B[rf[i]].sum2());
}
}
int query(int u) { // 查询
int res(0);
for (int i = u; i; i = rf[i])
if (B[i].size() > 2 || !sit[i])
res = max(res, B[i].sum2());
return res;
}
}
int main() {
qio();
cin >> n;
for (int i = 1, u, v; i < n; i++) {
cin >> u >> v;
G[u].push_back({v, 1});
G[v].push_back({u, 1});
}
LCA::init();
DCT::f[DCT::rt = 0] = inf, DCT::sum = n;
DCT::centroid(1, 0);
DCT::centroid(DCT::rt, 0);
deletable_heap < vertex > q;
L(i, 1, n)
q.push({i, dis(i, dist[i] = DCT::rt)});
DCT::rebuild(DCT::rt, 0);
L(i, 1, n)
DCT::A[i].push(0), DCT::B[i].push(0);
DCT::init();
char ch;
int Q, u, sum = n; // sum 记录还关着的灯
cin >> Q;
while (Q--) {
cin >> ch;
if (ch == 'C') {
cin >> u;
if (sit[u]) { // sit[u] == 1: light
DCT::off(u);
q.push({u, dist[u]});
sum++;
} else {
DCT::light(u);
q.remove({u, dist[u]});
sum--;
}
sit[u] ^= 1; // 改变状态
} else {
printf("%d\n", sum ? (sum == 1 ? 0 : DCT::query(q.top().u)) : -1);
}
}
return 0;
}