题目大意:给你一棵树,有$3$个操作:
- $Q;p;q:$询问$p,q$是否连通
- $C;p;q:$把$p->q$这条边割断
- $U;x:$恢复第$x$次操作二
题解:可以在割断时把这条边赋值上$1$,恢复时赋成$0$,只需要求$p->q$路径和是否为$0$即可,可以用$dfs$序+树状数组维护
卡点:$LCA$越界
C++ Code:
#include <cstdio> #include <cctype> #include <algorithm> namespace __IO { namespace R { int x, ch; inline int read() { ch = getchar(); while (isspace(ch)) ch = getchar(); for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15); return x; } } } using __IO::R::read; #define maxn 300010 int head[maxn], cnt; struct Edge { int to, nxt; } e[maxn << 1]; inline void add(int a, int b) { e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt; } int n, m; #define M 20 int fa[maxn][M], sz[maxn], dep[maxn], dfn[maxn], idx; void dfs(int u) { dfn[u] = ++idx; sz[u] = 1; for (int i = 1; i < M; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != *fa[u]) { *fa[v] = u; dep[v] = dep[u] + 1; dfs(v); sz[u] += sz[v]; } } } inline int LCA(int x, int y) { if (x == y) return x; if (dep[x] < dep[y]) std::swap(x, y); for (int i = dep[x] - dep[y]; i; i &= i - 1) x = fa[x][__builtin_ctz(i)]; if (x == y) return x; for (int i = M - 1; ~i; i--) if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return *fa[x]; } namespace BIT { int Tr[maxn], res; inline void modify(int p, int num) {for (; p <= n; p += p & -p) Tr[p] += num;} inline int query(int p) {for (res = 0; p; p &= p - 1) res += Tr[p]; return res;} } inline void modify(int x, int num) { BIT::modify(dfn[x], num); BIT::modify(dfn[x] + sz[x], -num); } inline void query(int x, int y) { int res = BIT::query(dfn[x]) + BIT::query(dfn[y]) - BIT::query(dfn[LCA(x, y)]) * 2; puts(res ? "No" : "Yes"); } int war[maxn], Tim; int main() { n = read(), m = read(); for (int i = 1, a, b; i < n; i++) { a = read(), b = read(); add(a, b); add(b, a); } dfs(1); while (m --> 0) { int x, y; char op = getchar(); while (!isalpha(op)) op = getchar(); switch (op) { case 'Q': x = read(), y = read(); query(x, y); break; case 'C': x = read(), y = read(); if (dep[x] < dep[y]) std::swap(x, y); war[++Tim] = x; modify(x, 1); break; case 'U': x = read(); modify(war[x], -1); break; } } return 0; }