学会了用priority_queue实现带删除操作的堆.
/* I will wait for you*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <string>
#define make make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int maxn = 200010;
const int maxm = 1010;
const int maxs = 26;
const int inf = 0x3f3f3f3f;
const int P = 1000000007;
const double error = 1e-9;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch <= 47 || ch >= 58)
f = (ch == 45 ? -1 : 1), ch = getchar();
while (ch >= 48 && ch <= 57)
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
struct edge
{
int v, next;
} e[maxn];
struct heap
{
priority_queue<int> A, B;
void push(int c) {
A.push(c);
}
void erase(int c) {
B.push(c);
}
void pop() {
while (B.size() && A.top() == B.top())
A.pop(), B.pop();
A.pop();
}
int size() {
return A.size() - B.size();
}
int first() {
while (B.size() && A.top() == B.top())
A.pop(), B.pop();
return A.size() ? A.top() : 0;
}
int second() {
if (size() < 2)
return 0;
int x, y;
x = first(), pop();
y = first(), push(x);
return y;
}
} A, B[maxn >> 1], C[maxn >> 1];
int n, m, root, cnt, dfn, sum, tot, bin[maxn], lg[maxn],
size[maxn], deep[maxn], sm[maxn], head[maxn], fa[maxn],
st[maxn][20], pos[maxn], del[maxn], col[maxn];
void insert(int u, int v)
{
e[cnt] = (edge) {v, head[u]}, head[u] = cnt++;
e[cnt] = (edge) {u, head[v]}, head[v] = cnt++;
}
void dfs(int u, int p)
{
st[++dfn][0] = deep[u], pos[u] = dfn;
for (int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if (v != p) {
deep[v] = deep[u] + 1, dfs(v, u);
st[++dfn][0] = deep[u];
}
}
}
void find(int u, int p)
{
size[u] = 1, sm[u] = 0;
for (int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if (v != p && !del[v]) {
find(v, u), size[u] += size[v];
sm[u] = max(sm[u], size[v]);
}
}
sm[u] = max(sm[u], sum - size[u]);
if (sm[u] < sm[root])
root = u;
}
void divide(int u, int p)
{
fa[u] = p, del[u] = 1;
for (int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if (v != p && !del[v]) {
sum = size[v], root = 0;
find(v, u), divide(root, u);
}
}
}
int lca(int u, int v)
{
u = pos[u], v = pos[v];
if (u > v)
swap(u, v);
int t = lg[v - u + 1];
return min(st[u][t], st[v - bin[t] + 1][t]);
}
int dis(int u, int v)
{
return deep[u] + deep[v] - 2 * lca(u, v);
}
void turn_off(int u, int p)
{
if (u == p) {
B[u].push(0);
if (B[u].size() == 2)
A.push(B[u].first());
}
if (!fa[p])
return;
int f = fa[p], d = dis(u, f), tmp = C[p].first();
C[p].push(d);
if (d > tmp) {
int mx = B[f].first() + B[f].second(),
size = B[f].size();
B[f].push(d);
if (tmp)
B[f].erase(tmp);
int now = B[f].first() + B[f].second();
if (now > mx) {
if (size >= 2)
A.erase(mx);
if (B[f].size() >= 2)
A.push(now);
}
}
turn_off(u, f);
}
void turn_on(int u, int p)
{
if (u == p) {
if (B[u].size() == 2)
A.erase(B[u].first());
B[u].erase(0);
}
if (!fa[p])
return;
int f = fa[p], d = dis(u, f), tmp = C[p].first();
C[p].erase(d);
if (d == tmp) {
int mx = B[f].first() + B[f].second(),
size = B[f].size();
B[f].erase(d);
if (C[p].first())
B[f].push(C[p].first());
int now = B[f].first() + B[f].second();
if (now < mx) {
if (size >= 2)
A.erase(mx);
if (B[f].size() >= 2)
A.push(now);
}
}
turn_on(u, f);
}
void init()
{
bin[0] = 1;
for (int i = 1; i <= 20; i++)
bin[i] = bin[i - 1] << 1;
lg[0] = -1;
for (int i = 1; i <= 200000; i++)
lg[i] = lg[i >> 1] + 1;
}
int main()
{
n = read(), init();
memset(head, -1, sizeof head);
for (int i = 1; i < n; i++) {
int u = read(), v = read();
insert(u, v);
}
dfs(1, 0);
for (int i = 1; i <= 20; i++)
for (int j = 1; j <= dfn; j++)
if (j + bin[i] - 1 <= dfn)
st[j][i] = min(st[j][i - 1], st[j + bin[i - 1]][i - 1]);
sm[0] = inf, root = 0, sum = n;
find(1, 0), divide(root, 0);
for (int i = 1; i <= n; i++)
C[i].push(0), col[i] = 1;
for (int i = 1; i <= n; i++)
turn_off(i, i);
m = read(), tot = n;
while (m--) {
char s[10]; scanf("%s", s);
if (s[0] == 'G') {
if (tot <= 1)
printf("%d\n", tot - 1);
else
printf("%d\n", A.first());
}
if (s[0] == 'C') {
int w = read();
if (col[w] == 1)
tot--, turn_on(w, w);
if (col[w] == 0)
tot++, turn_off(w, w);
col[w] ^= 1;
}
}
return 0;
}