题目大意:给你一棵树,有$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;
}