# UOJ207 共价大爷游长沙

## Description

1. 删除树中的一条边，并且再连接一条边，满足操作之后仍然一棵树

2. 往集合中加入一条路径

3. 删去第$x$次往集合里加入的路径

4. 询问树上的一条边是否被集合中所有的路径经过

$n \leq 10^5, m \leq 3 \cdot 10^5$

## Code

#include <bits/stdc++.h>

using namespace std;

#define fst first
#define snd second
#define mp make_pair
#define squ(x) ((LL)(x) * (x))
#define debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef pair<int, int> pii;

template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }

int sum = 0, fg = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
return fg * sum;
}

typedef unsigned long long ULL;

static random_device rd;

inline ULL get_rand() { return ((ULL) rd() << 32) | rd(); }

const int maxn = 1e5 + 10;
const int maxm = 3e5 + 10;

namespace LCT {
struct node {
bool rev;
int son[2], f;
ULL v, s, x;
}A[maxn];
#define ls(x) A[x].son[0]
#define rs(x) A[x].son[1]
#define fa(x) A[x].f

inline void push_up(int x) { A[x].s = A[x].v ^ A[x].x ^ A[ls(x)].s ^ A[rs(x)].s; } /**/
inline void push_down(int x) {
if (A[x].rev) {
swap(ls(x), rs(x));
A[ls(x)].rev ^= 1, A[rs(x)].rev ^= 1, A[x].rev = 0;
}
}

inline bool chkrt(int x) { return x != ls(fa(x)) && x != rs(fa(x)); }
inline bool chk(int x) { return x == rs(fa(x)); }
inline void link(int x, int y, int f) { fa(x) = y, A[y].son[f] = x; }
inline void rotate(int x) {
int f = fa(x), dx = chk(x), df = chk(f);
if (!chkrt(f)) link(x, fa(f), df); else fa(x) = fa(f);
push_up(f), push_up(x);
}
inline void splay(int x) {
static int S[maxn]; S[++S[0]] = x;
for (int y = x; !chkrt(y); y = fa(y)) S[++S[0]] = fa(y);
while (S[0]) push_down(S[S[0]--]);
while (!chkrt(x)) { if (!chkrt(fa(x))) rotate(chk(x) == chk(fa(x)) ? fa(x) : x); rotate(x); }
}

inline void access(int x) { int _x = x; for (int lst = 0; x; x = fa(lst = x)) splay(x), A[x].x ^= A[rs(x)].s ^ A[lst].s, rs(x) = lst, push_up(x); splay(_x); }
inline void mkrt(int x) { access(x), A[x].rev ^= 1, push_down(x); }
inline int getrt(int x) { access(x); while (ls(x)) push_down(x = ls(x)); return x; }
inline void split(int x, int y) { mkrt(x), access(y); }
inline void Link(int x, int y) { mkrt(x), access(y); fa(x) = y, A[y].x ^= A[x].s; }
inline void Cut(int x, int y) { split(x, y), fa(x) = 0, ls(y) = 0, push_up(y); }

inline void modify(int x, ULL v) { mkrt(x), A[x].v ^= v, push_up(x); }
inline ULL query(int x) { access(x); return A[x].v ^ A[x].x; }
}

ULL w[maxm], Sum;
int X[maxm], Y[maxm], cnt;

int n, m;

int main() {
#ifdef xunzhen
freopen("travel.in", "r", stdin);
freopen("travel.out", "w", stdout);
#endif

for (int i = 1; i < n; i++) {
}

for (int i = 1; i <= m; i++) {
if (op == 1) {
LCT::Cut(x, y);
}
if (op == 2) {
w[++cnt] = get_rand(), X[cnt] = x, Y[cnt] = y;
LCT::modify(x, w[cnt]), LCT::modify(y, w[cnt]);
Sum ^= w[cnt];
}
if (op == 3) {
LCT::modify(X[x], w[x]), LCT::modify(Y[x], w[x]);
Sum ^= w[x];
}
if (op == 4) {