树剖虚点求助
查看原帖
树剖虚点求助
756660
B612Dusk楼主2024/8/14 10:46

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;
}
2024/8/14 10:46
加载中...