nfds是并查集,ft是树状数组,思路是对于修改从x到find(x) 加上 qry[y] ,c[x]表示当前下 x 的子树大小的差分数组
码风自认不算太丑
#include <bits/stdc++.h>
#define pb push_back
using std::cin;
using std::cout;
using std::endl;
const int N = 1e5 + 10;
inline int max(int x, int y) { return x > y ? x : y; }
inline int min(int x, int y) { return x < y ? x : y; }
inline void swap(int &x, int &y) { x ^= y ^= x ^= y; }
inline int read()
{
int t;
cin >> t;
return t;
}
int n, Q;
struct quest{
int x, y, op;
}que[N];
int nxt[N << 1], ver[N << 1];
int head[N], tot;
inline void add(int a, int b)
{
nxt[++ tot] = head[a], ver[tot] = b;
head[a] = tot;
}
namespace ufds // (Union-Find Disjoint Set) 并查集
{
int fa[N], sze[N];
void org() { for(int i = 1;i <= n;i = -~i) fa[i] = i, sze[i] = 1; }
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
inline void merge(int x, int y)
{
int fx = find(x), fy = find(y);
if(sze[fx] < sze[fy]) swap(fx, fy);
fa[fy] = fx;
sze[fx] += sze[fy];
}
}
namespace ft // (Fenwick Tree) 树状数组
{
int c[N];
#define lowbit(x) x & (-x)
void add(int x, int v, int n)
{
for(; x <= n; x += lowbit(x))
c[x] += v;
}
int qry(int x, int n)
{
int val = 0;
for(; x; x -= lowbit(x))
val += c[x]; return val;
}
}
int rt;
int fa[N], sze[N], dep[N], son[N];
void get_son(int x, int Fa)
{
fa[x] = Fa, sze[x] = 1, dep[x] = dep[Fa] + 1;
for(int i = head[x]; i; i = nxt[i])
{
int y = ver[i];
if(y == Fa) continue;
get_son(y, x);
sze[x] += sze[y];
if(sze[son[x]] < sze[y]) son[x] = y;
}
}
int dfn[N], nfd[N], top[N], idx;
void get_chain(int x, int Top)
{
top[x] = Top, dfn[x] = ++ idx, nfd[idx] = x;
if(!son[x]) return;
get_chain(son[x], Top);
for(int i = head[x]; i; i = nxt[i])
{
int y = ver[i];
if(y == fa[x] || y == son[x]) continue;
get_chain(y, y);
}
}
inline void ch_mtf(int x, int y, int v)
{
while(top[x] ^ top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ft::add(dfn[top[x]], v ,n);
ft::add(dfn[x] + 1, -v, n);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ft::add(dfn[x], v, n);
ft::add(dfn[y] + 1, -v, n);
}
signed main()
{
// freopen("P4219_2.in", "r", stdin);
// freopen("", "w", stdout);
std::ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
n = read(), Q = read();
ufds::org();
for(int i = 1;i <= Q;i = -~i)
{
char op;
cin >> op;
int x = read(), y = read();
if(op == 'A') add(x, y), add(y, x), ufds::merge(x, y);
que[i] = (quest) {x, y, op - 'A'};
}
rt = ++ n;
for(int i = 1;i <= n;i = -~i)
if(ufds::find(i) == i) add(rt, i), add(i, rt);
get_son(rt, rt);
get_chain(rt, rt);
ft::add(1, 1, n); // c = dert(a)
ufds::org();
for(int i = 1;i <= Q;i = -~i)
{
bool op = que[i].op;
int x = que[i].x, y = que[i].y;
if(dep[x] > dep[y]) swap(x, y);
if(!op)
{
ch_mtf(x, ufds::find(x), ft::qry(dfn[y], n));
ufds::merge(x, y);
// cout << (ft::qry(dfn[ufds::find(x)], n) - ft::qry(dfn[y], n)) * ft::qry(dfn[y], n) << endl;
}
else
cout << (ft::qry(dfn[ufds::find(x)], n) - ft::qry(dfn[y], n)) * ft::qry(dfn[y], n) << endl;
}
return 0;
}