萌新刚学树剖求助
查看原帖
萌新刚学树剖求助
134000
Plozia楼主2021/3/9 20:44

萌新昨天刚学树剖,现在不知道这道题是哪里炸了,求助各位大佬!

思路跟题解区写树剖的大佬差不多,目前根据个人分析,可能是在 Segment_treechange,add 函数以及循环环节出错。

出错位置以及相应函数变量功能代码里面有标注。

再次拜托各位大佬了!

/*
========= Plozia =========
	Author:Plozia
	Problem:P2486 [SDOI2011]染色
	Date:2021/3/9
========= Plozia =========
*/

#include <bits/stdc++.h>
using std::vector;

typedef long long LL;
const int MAXN = 1e5 + 10;
int n, m, wfir[MAXN];
int Size[MAXN], Son[MAXN], dep[MAXN], fa[MAXN], Top[MAXN], id[MAXN], w[MAXN], cnt;//树剖的一些基本数组
vector <int> Next[MAXN];//存图
struct node
{
	int firnum, lasnum;//首元素,尾元素
	int sum, l, r, add;//区间答案,左端点,右端点,lazy_tag
	#define l(p) tree[p].l
	#define r(p) tree[p].r
	#define s(p) tree[p].sum
	#define a(p) tree[p].add
	#define fir(p) tree[p].firnum
	#define las(p) tree[p].lasnum
}tree[MAXN << 2];

int read()
{
	int sum = 0, fh = 1; char ch = getchar();
	for (; ch < '0' || ch > '9'; ch = getchar()) fh -=  (ch == '-') << 1;
	for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = (sum << 3) + (sum << 1) + (ch ^ 48);
	return (fh == 1) ? sum : -sum;
}

namespace Segment_tree//线段树的 namespace
{
	void build(int p, int l, int r)//建树
	{
		l(p) = l, r(p) = r;
		if (l == r) {s(p) = 1; fir(p) = las(p) = w[l]; return ;}
		int mid = (l + r) >> 1;
		build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r);
		s(p) = s(p << 1) + s(p << 1 | 1);
		if (las(p << 1) == fir(p << 1 | 1)) --s(p);
		fir(p) = fir(p << 1), las(p) = las(p << 1 | 1);
	}
	
	void spread(int p)//线段树下传 lazy_tag
	{
		if (a(p))
		{
			s(p << 1) = s(p << 1 | 1) = 1; 
			a(p << 1) = a(p << 1 | 1) = a(p);
			fir(p << 1) = fir(p << 1 | 1) = las(p << 1) = las(p << 1 | 1) = a(p);
			a(p) = 0;
		}
	}
	
	void change(int p, int l, int r, int c)//可能出错的地方 1,线段树区间推平
	{
		if (l(p) >= l && r(p) <= r) {s(p) = 1; a(p) = fir(p) = las(p) = c; return ;}
		spread(p);
		int mid = (l(p) + r(p)) >> 1;
		if (l <= mid) change(p << 1, l, r, c);
		if (r > mid) change(p << 1 | 1, l, r, c);
		s(p) = s(p << 1) + s(p << 1 | 1);
		if (las(p << 1) == fir(p << 1 | 1)) --s(p);
		fir(p) = fir(p << 1), las(p) = las(p << 1 | 1);
	}
	
	int ask(int p, int l, int r)//可能出错的地方 2,线段树区间查询
	{
		if (l(p) >= l && r(p) <= r) return s(p);
		spread(p);
		int mid = (l(p) + r(p)) >> 1, ans = 0;
		if (l <= mid && r > mid)
		{
			ans = ask(p << 1, l, r) + ask(p << 1 | 1, l, r);
			if (las(p << 1) == fir(p << 1 | 1)) --ans;
		}
		else if (l <= mid) ans = ask(p << 1, l, r);
		else if (r > mid) ans = ask(p << 1 | 1, l, r);
		return ans;
	}
}

void dfs1(int now, int father, int depth)//树剖 dfs1
{
	dep[now] = depth; fa[now] = father; Size[now] = 1;
	for (int i = 0; i < Next[now].size(); ++i)
	{
		int u = Next[now][i];
		if (u == father) continue;
		dfs1(u, now, depth + 1);
		Size[now] += Size[u];
		if (Size[u] > Size[Son[now]]) Son[now] = u;
	}
}

void dfs2(int now, int top_father)//树剖 dfs2
{
	id[now] = ++cnt; Top[now] = top_father; w[cnt] = wfir[now];
	if (!Son[now]) return ;
	dfs2(Son[now], top_father);
	for (int i = 0; i < Next[now].size(); ++i)
	{
		int u = Next[now][i];
		if (u == fa[now] || u == Son[now]) continue;
		dfs2(u, u);
	}
}

int main()
{
	n = read(), m = read();
	for (int i = 1; i <= n; ++i) wfir[i] = read();
	for (int i = 1; i < n; ++i)
	{
		int x = read(), y = read();
		Next[x].push_back(y), Next[y].push_back(x);
	}
	dfs1(1, 1, 1); dfs2(1, 1); Segment_tree::build(1, 1, n);
	for (int i = 1; i <= m; ++i)
	{
		char ch = getchar();
		while (ch == ' ' || ch == '\n' || ch == '\r') ch = getchar();
		if (ch == 'C')
		{
			int a = read(), b = read(), c = read();
			while (Top[a] != Top[b])
			{
				if (dep[Top[a]] < dep[Top[b]]) std::swap(a, b);
				Segment_tree::change(1, id[Top[a]], id[a], c);
				a = fa[Top[a]];
			}
			if (dep[a] > dep[b]) std::swap(a, b);
			Segment_tree::change(1, id[a], id[b], c);
		}
		if (ch == 'Q')//可能出错的地方 3
		{
			int a = read(), b = read(), ans = 0;
			while (Top[a] != Top[b])
			{
				if (dep[Top[a]] < dep[Top[b]]) std::swap(a, b);
				ans += Segment_tree::ask(1, id[Top[a]], id[a]);
				if (Segment_tree::ask(1, id[Top[a]], id[Top[a]]) == Segment_tree::ask(1, id[fa[Top[a]]], id[fa[Top[a]]])) --ans;
				a = fa[Top[a]];
			}
			if (dep[a] > dep[b]) std::swap(a, b);
			ans += Segment_tree::ask(1, id[a], id[b]);
			printf("%d\n", ans);
		}
	}
	return 0;
}
2021/3/9 20:44
加载中...