树剖 前一半全 A 后一半全 W 求调
查看原帖
树剖 前一半全 A 后一半全 W 求调
563650
haochengw920楼主2024/3/30 23:41

rt,这题貌似也不用开 long long 啊

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

const int MAXN = 1000005;

int n, Q;
int w[MAXN];
struct edge {
	int to, nex;
}e[MAXN << 1]; int idx, head[MAXN];
inline void add(int u, int v) {
	e[++ idx].to = v;
	e[idx].nex = head[u];
	head[u] = idx;
}

int timer, dfn[MAXN], id[MAXN];
int fa[MAXN], dep[MAXN], siz[MAXN];
int top[MAXN], wson[MAXN];
inline void dfs1(int u) {
	siz[u] = 1;
	if (u == 1) dep[u] = 1;
	for (int i = head[u]; i; i = e[i].nex) {
		int v = e[i].to;
		if (v == fa[u]) continue;
		fa[v] = u; dep[v] = dep[u] + 1;
		dfs1(v); siz[u] += siz[v];
		if (siz[v] > siz[wson[u]])
			wson[u] = v;
	}
}
inline void dfs2(int u, int bel) {
	top[u] = bel;
	id[dfn[u] = ++ timer] = u;
	if (wson[u]) dfs2(wson[u], bel);
	for (int i = head[u]; i; i = e[i].nex) {
		int v = e[i].to;
		if (v == fa[u] || v == wson[u])
			continue;
		dfs2(v, v);
	}
}

class Segment_tree {
	#define lc (u << 1)
	#define rc (u << 1 | 1)
	private : 
	struct node {
		int lcl, rcl;
		int sum, col;
	}tr[MAXN << 2];
	inline void push_up(int u) {
		tr[u].lcl = tr[lc].lcl;
		tr[u].rcl = tr[rc].rcl;
		tr[u].sum = tr[lc].sum + tr[rc].sum;
		if (tr[lc].rcl == tr[rc].lcl)
			-- tr[u].sum;
	}
	inline void push_down(int u) {
		if (!tr[u].col) return;
		int tg = tr[u].col;
		tr[u].col = 0;
		tr[lc].col = tr[rc].col = tg;
		tr[lc].lcl = tr[lc].rcl = tg;
		tr[rc].lcl = tr[rc].rcl = tg;
		tr[lc].sum = tr[rc].sum = 1;
	}
	public : 
	inline void Build(int u = 1, int l = 1, int r = n) {
		if (l == r) {
			tr[u].sum = 1; 
			tr[u].lcl = tr[u].rcl = w[id[l]];
			return;
		}
		int mid = (l + r) >> 1;
		Build(lc, l, mid);
		Build(rc, mid + 1, r);
		push_up(u);
	}
	inline void Modify(int bg, int nd, int x, int u = 1, int l = 1, int r = n) {
		if (bg <= l && r <= nd) {
			tr[u].col = x;
			tr[u].lcl = tr[u].rcl = x;
			tr[u].sum = 1;
			return;
		}
		push_down(u);
		int mid = (l + r) >> 1;
		if (bg <= mid) Modify(bg, nd, x, lc, l, mid);
		if (nd > mid) Modify(bg, nd, x, rc, mid + 1, r);
		push_up(u);
	}
	inline int Query(int bg, int nd, int &lct, int &rct, int u = 1, int l = 1, int r = n) {
		if (bg <= l && r <= nd) {
			if (bg == l) lct = tr[u].lcl;
			if (nd == r) rct = tr[u].rcl;
			return tr[u].sum;
		}
		int mid = (l + r) >> 1;
		push_down(u);
		if (nd <= mid) return Query(bg, nd, lct, rct, lc, l, mid);
		if (bg > mid) return Query(bg, nd, lct, rct, rc, mid + 1, r);
		int res = Query(bg, nd, lct, rct, lc, l, mid);
		res +=  Query(bg, nd, lct, rct, rc, mid + 1, r);
		if (tr[lc].rcl == tr[rc].lcl) -- res;
		return res;
	}
	#undef lc
	#undef rc
}st;

inline void Chg(int u, int v, int col) {
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]])
			swap(u, v); 
		st.Modify(dfn[top[u]], dfn[u], col);
		u = fa[top[u]];
	}
	if (dep[u] > dep[v]) swap(u, v);
	st.Modify(dfn[u], dfn[v], col);
}
inline int Qry(int u, int v) {
	int res = 0;
	int lst1 = -1, lst2 = -1;
	int Lt, Rt;
	while (top[u] != top[v]) {
		if (dep[top[u]] < dep[top[v]])
			swap(u, v), swap(lst1, lst2);
		res += st.Query(dfn[top[u]], dfn[u], Lt, Rt);
		res -= (Rt == lst1); lst1 = Lt;
		u = fa[top[u]];
	}
	if (dep[u] > dep[v]) 
		swap(u, v);
	res += st.Query(dfn[u], dfn[v], Lt, Rt);
	if (Lt == lst1) -- res;
	if (Rt == lst2) -- res;
	return res;
}

int main()
{
	scanf ("%d%d", &n, &Q);
	for (int i = 1; i <= n; ++ i)
		scanf ("%d", w + i);
	for (int i = 1; i < n; ++ i) {
		int u, v;
		scanf ("%d%d", &u, &v);
		add(u, v); add(v, u);
	}
	dfs1(1); dfs2(1, 1);
	st.Build();
	char op[MAXN];
	int a, b, c;
	while (Q --) {
		scanf ("%s", op);
		if (op[0] == 'C') {
			scanf ("%d%d%d", &a, &b, &c);
			Chg(a, b, c);
		} else {
			scanf ("%d%d", &a, &b);
			printf ("%d\n", Qry(a, b));
		}
	}
	return 0;
}
2024/3/30 23:41
加载中...