Problem
Description
Given a tree.
You need to address the following three things, all events are presented in chronological order.
\ (Q, u, v \ ) representative asked \ (u, v \) can reach each other
\ (C, u, v \ ) Representative \ (u, v \) between the OFF edge
\ (U, x \) represents the \ (the U-\) times \ (C \) operation is restored
Input Format
The first line of the two numbers \ (n \) and \ (m \) , \ (n \) represents a total of \ (n \) tribes, \ (m \) represents the total of these three events
The next \ (n - 1 \) lines of two numbers \ (P, Q \) , represents the first \ (P \) points to the first \ (Q \) there is connected a road between points
The next \ (m \) rows, each row represents an operation, detailed description of the subject.
Output Format
For each \ (Q \) operations are given in a row Yes
or No
on behalf result of the inquiry.
Range
\ (N, m \ 3 * 10 ^ 5 \)
Algorithm
Fenwick tree
Mentality
In fact, I wanted to practice hand look \ (LCT \) , but this problem by \ (LCT \) it seems overkill ......
Looked at roughly solution to a problem, with all the trees and cross \ (LCT \) like this, but in fact there is a very simple way, just Fenwick tree + random number.
The subject, for a path \ (u, v \) , this path Unicom iff \ (u, v \) sides have not been turned off on.
So how can we satisfy this condition is it? Replaced by requirements for off side, that is, for all current off the edge, \ (U, v \) or are within its sub-tree, or none at.
Then we can consider \ (dfn \) sequence + Fenwick tree maintenance sub-tree information, whenever each side of the break, Ode to each point within a sub-tree-specific information, and then when asked for \ ( u, v \) query the information above is equal to.
Fu special information on how to do this? Very simple, for each side are broken \ (rand \) a specific weight, all nodes in a tree within the sub-array to add this tree are the right values.
When the query need only check two things are the same weight on the line.
Reduction of time and then deleted just fine.
Code
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
#define LL long long
#define go(G, x, i, v) \
for (int i = G.hd[x], v = G.to[i]; i; v = G.to[i = G.nx[i]])
#define inline __inline__ __attribute__((always_inline))
inline LL read() {
LL x = 0, w = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') w = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}
return x * w;
}
const int Max_n = 3e5 + 5, mod = 998244353;
int n, m;
int cntd, dep[Max_n], dfn[Max_n], siz[Max_n];
int c[Max_n];
struct graph {
int hd[Max_n];
int cntr, nx[Max_n << 1], to[Max_n << 1];
void addr(int u, int v) {
cntr++;
nx[cntr] = hd[u], to[cntr] = v;
hd[u] = cntr;
}
} G;
struct que {
int u, v, x;
} k[Max_n];
namespace Input {
void main() {
n = read(), m = read();
int u, v;
for (int i = 1; i < n; i++) {
u = read(), v = read();
G.addr(u, v), G.addr(v, u);
}
}
} // namespace Input
namespace Init {
void build(int x, int fa) {
dep[x] = dep[fa] + 1, siz[x] = 1, dfn[x] = ++cntd;
go(G, x, i, v) if (v != fa) build(v, x), siz[x] += siz[v];
}
void main() { build(1, 0); }
} // namespace Init
namespace Solve {
void add(int k, int x) {
for (int i = k; i <= n; i += i & -i) (c[i] += x) %= mod;
}
int query(int k) {
int ans = 0;
for (int i = k; i; i -= i & -i) (ans += c[i]) %= mod;
return (ans + mod) % mod;
}
void main() {
srand((unsigned)time(NULL));
int cnt = 0, u, v;
char op;
for (int i = 1; i <= m; i++) {
scanf(" %c", &op);
u = read();
if (op == 'U')
add(dfn[k[u].v], -k[u].x), add(dfn[k[u].v] + siz[k[u].v], k[u].x);
else {
v = read();
if (op == 'Q')
printf("%s\n", query(dfn[u]) == query(dfn[v]) ? "Yes" : "No");
else {
k[++cnt].x = rand() % mod;
if (dep[u] > dep[v]) swap(u, v);
add(dfn[v], k[cnt].x), add(dfn[v] + siz[v], -k[cnt].x);
k[cnt].u = u, k[cnt].v = v;
}
}
}
}
} // namespace Solve
int main() {
#ifndef ONLINE_JUDGE
freopen("3950.in", "r", stdin);
freopen("3950.out", "w", stdout);
#endif
Input::main();
Init::main();
Solve::main();
}