2022年02月04日,第十六天
1. 题目链接:P2147 [SDOI2008] 洞穴勘测
思路: L C T LCT LCT 在线解决,时间复杂度 O ( m l o g n ) O(mlog\ n) O(mlog n) ,常数巨大。模板题,不必多言。
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define re register
#define endl '\n'
using namespace std;
const int MOD = 998244353;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double Pi = acos(-1.0);
const int N = 1e5 + 5;
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
int ch[N][2], fa[N];
int siz[N], rev[N];
int n, m, st[N], top;
inline int ident (int x, int f) { return rs(f) == x; }
inline bool isroot (int x) {
return ls(fa[x]) != x && rs(fa[x]) != x;
}
inline void pushup (int x) {
siz[x] = siz[ls(x)] + siz[rs(x)] + 1;
}
inline void pushrev (int x) {
swap (ls(x), rs(x));
rev[x] ^= 1;
}
inline void pushdown (int x) {
if (rev[x]) {
if (ls(x)) pushrev (ls(x));
if (rs(x)) pushrev (rs(x));
rev[x] = 0;
}
}
inline void rotate (int x) {
int y = fa[x], z = fa[y], k = ident (x, y);
if (! isroot (y)) ch[z][ident (y, z)] = x;
ch[y][k] = ch[x][k ^ 1], ch[x][k ^ 1] = y;
if (ch[y][k]) fa[ch[y][k]] = y;
fa[x] = z, fa[y] = x;
pushup (y), pushup (x);
}
inline void splay (int x) {
int r = x;
st[top = 1] = r;
while (! isroot (r)) st[++ top] = r = fa[r];
while (top) pushdown (st[top --]);
while (! isroot (x)) {
int y = fa[x], z = fa[y];
if (! isroot (y))
rotate (ident (x, y) ^ ident (y, z) ? x : y);
rotate (x);
}
pushup (x);
}
inline void access (int x) {
for (int y = 0; x; x = fa[y = x])
splay (x), rs(x) = y, pushup (x);
}
inline void makeroot (int x) {
access (x);
splay (x);
pushrev (x);
}
inline int findroot (int x) {
access (x), splay (x);
while (ls(x)) pushdown (x), x = ls(x);
splay (x);
return x;
}
inline void split (int x, int y) {
makeroot (x);
access (y);
splay (y);
}
inline void link (int x, int y) {
makeroot (x);
if (findroot (y) != x)
fa[x] = y;
}
inline void cut (int x, int y) {
makeroot (x);
if (findroot (y) == x && fa[y] == x && ! ls(y))
fa[y] = rs(x) = 0, pushup (x);
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
while (m --) {
char op[20];
int u, v;
cin >> op >> u >> v;
if (* op == 'C') link (u, v);
if (* op == 'D') cut (u, v);
if (* op == 'Q')
if (findroot (u) == findroot (v)) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
return 0;
}
2. 题目链接:P3950 部落冲突
思路: L C T LCT LCT 在线解决,时间复杂度 O ( m l o g n ) O(mlog\ n) O(mlog n) ,常数巨大。模板题,不必多言。
#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define re register
#define endl '\n'
using namespace std;
const int MOD = 998244353;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double Pi = acos(-1.0);
const int N = 3e5 + 5;
#define ls(x) (ch[x][0])
#define rs(x) (ch[x][1])
int ch[N][2], fa[N];
int siz[N], rev[N];
int n, m, st[N], top;
int a[N], b[N], cnt;
inline int ident (int x, int f) { return rs(f) == x; }
inline bool isroot (int x) {
return ls(fa[x]) != x && rs(fa[x]) != x;
}
inline void pushup (int x) {
siz[x] = siz[ls(x)] + siz[rs(x)] + 1;
}
inline void pushrev (int x) {
swap (ls(x), rs(x));
rev[x] ^= 1;
}
inline void pushdown (int x) {
if (rev[x]) {
if (ls(x)) pushrev (ls(x));
if (rs(x)) pushrev (rs(x));
rev[x] = 0;
}
}
inline void rotate (int x) {
int y = fa[x], z = fa[y], k = ident (x, y);
if (! isroot (y)) ch[z][ident (y, z)] = x;
ch[y][k] = ch[x][k ^ 1], ch[x][k ^ 1] = y;
if (ch[y][k]) fa[ch[y][k]] = y;
fa[x] = z, fa[y] = x;
pushup (y), pushup (x);
}
inline void splay (int x) {
int r = x;
st[top = 1] = r;
while (! isroot (r)) st[++ top] = r = fa[r];
while (top) pushdown (st[top --]);
while (! isroot (x)) {
int y = fa[x], z = fa[y];
if (! isroot (y))
rotate (ident (x, y) ^ ident (y, z) ? x : y);
rotate (x);
}
pushup (x);
}
inline void access (int x) {
for (int y = 0; x; x = fa[y = x])
splay (x), rs(x) = y, pushup (x);
}
inline void makeroot (int x) {
access (x);
splay (x);
pushrev (x);
}
inline int findroot (int x) {
access (x), splay (x);
while (ls(x)) pushdown (x), x = ls(x);
splay (x);
return x;
}
inline void split (int x, int y) {
makeroot (x);
access (y);
splay (y);
}
inline void link (int x, int y) {
makeroot (x);
if (findroot (y) != x)
fa[x] = y;
}
inline void cut (int x, int y) {
makeroot (x);
if (findroot (y) == x && fa[y] == x && ! ls(y))
fa[y] = rs(x) = 0, pushup (x);
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i < n; i ++) {
int u, v; cin >> u >> v;
link (u, v);
}
while (m --) {
char op[2]; int u, v;
cin >> op;
if (* op == 'U') {
cin >> u;
link (a[u], b[u]);
}
if (* op == 'C') {
cin >> u >> v;
a[++ cnt] = u, b[cnt] = v;
cut (u, v);
}
if (* op == 'Q') {
cin >> u >> v;
if (findroot (u) == findroot (v)) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
return 0;
}