学会了用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; }