树剖模板求助
查看原帖
树剖模板求助
306962
MVP_Harry楼主2020/8/29 11:43

RT,样例第二个输出一直是18,调了好久还是没找出错误QwQ感觉应该不是建树/dfs/更新子树的锅。代码风格还不错,有相应的注释,求大佬帮忙,谢谢!

#include<bits/stdc++.h>
using namespace std;
#define rep(i, m, n) for(int i = m; i <= n; i++)
#define per(i, m, n) for(int i = m; i >= n; i--)
#define pb push_back
#define vi vector<int> 
const int INF = 0x3f3f3f3f;

const int maxn = 1e5 + 5;

struct SegmentTree {
	int x, lazy;
} T[maxn << 2]; 
vi G[maxn]; //邻接表存图
int w[maxn], wt[maxn], dep[maxn], par[maxn], siz[maxn], id[maxn], son[maxn], top[maxn], rk[maxn], cnt, N, Q, mod, Root, res;
//跟第一个题解差不多,w是最初始的,wt是剖分完之后对应的,par是父节点,id是新的编号,siz是子树大小,rk好像没啥用,top是重链开始结点,res是后面query要用的。


/* ------------ dfs -----------------*/
void dfs1(int u, int k, int depth) {
	par[u] = k, dep[u] = depth, siz[u] = 1;
	for (int i = 0; i < (int) G[u].size(); i++) {
		int v = G[u][i];
		if (v == k) continue;
		dfs1(v, u, depth + 1);
		siz[u] += siz[v];
		if (siz[v] > siz[son[u]]) son[u] = v;
	}
}

void dfs2(int u, int t) {
	top[u] = t, id[u] = ++cnt, rk[cnt] = u, wt[cnt] = w[u];
	if (!son[u]) return ;
	dfs2(son[u], t);
	for (int i = 0; i < (int) G[u].size(); i++) {
		int v = G[u][i];
		if (v != par[u] && v != son[u]) dfs2(v, v);
	}
}

/* --------------- 线段树部分 --------------- */

inline void pushdown(int p, int s, int t) {
	int mid = (s + t) >> 1;
	T[p << 1].lazy = (T[p].lazy + T[p << 1].lazy), T[p << 1 | 1].lazy = (T[p].lazy + T[p << 1 | 1].lazy);
	T[p << 1].x = (T[p << 1].x + T[p].lazy * (mid - s + 1)) % mod;
	T[p << 1 | 1].x = (T[p << 1 | 1].x + T[p].lazy * (t - mid)) % mod;
	T[p].lazy = 0;
}

inline void build(int p, int s, int t) {
	if (s == t) {
		T[p].x = wt[s] % mod;
		return ;
	} 
	int mid = (s + t) >> 1;
	build(p << 1, s, mid), build(p << 1 | 1, mid + 1, t);
	T[p].x = (T[p << 1].x + T[p << 1 | 1].x) % mod;
}

inline void query(int l, int r, int s, int t, int p) {
	if (l <= s && r >= t) { res = (res + T[p].x) % mod; return ; }
	if (T[p].lazy) pushdown(p, s, t);
	int mid = (s + t) >> 1;
	if (l <= mid) query(l, r, s, mid, p << 1);
	if (r > mid) query(l, r, mid + 1, t, p << 1 | 1);
}

inline void update(int l, int r, int c, int s, int t, int p) {
	if (l <= s && r >= t) {
		T[p].lazy += c;
		T[p].x = (T[p].x + (t - s + 1) * c) % mod;
		return ;
	} 
	int mid = (s + t) >> 1;
	if (T[p].lazy) pushdown(p, s, t);
	if (l <= mid) update(l, r, c, s, mid, p << 1);
	if (r > mid) update(l, r, c, mid + 1, t, p << 1 | 1);
	T[p].x = (T[p << 1].x + T[p << 1 | 1].x) % mod;
}

/* -------------相应的更新区间/子树;查询区间/子树 -------------- */

inline int RangeQuery(int x, int y) {
	int ans = 0;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		res = 0;
		query(id[top[x]], id[x], 1, N, 1);
		ans = (ans + res) % mod;
		x = par[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	res = 0;
	query(id[x], id[y], 1, N, 1);
	ans = (ans + res) % mod;
	return ans;
}

inline void RangeUpdate(int x, int y, int k) {
	k %= mod;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		update(id[top[x]], id[x], k, 1, N, 1);
		x = par[top[x]];
	}
	if (dep[top[x]] > dep[top[y]]) swap(x, y);
	update(id[x], id[y], k, 1, N, 1);
}

inline int SonQuery(int x) {
	res = 0;
	query(id[x], id[x] + siz[x] - 1, 1, N, 1);
	return res;
}

inline void SonUpdate(int x, int c) {
	update(id[x], id[x] + siz[x] - 1, c, 1, N, 1);
}

int main() {
	ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N >> Q >> Root >> mod;
    rep(i, 1, N) cin >> w[i];
    rep(i, 1, N - 1) {
    	int u, v;
    	cin >> u >> v;
    	G[u].pb(v), G[v].pb(u);
    }
    dfs1(Root, 0, 1);
    dfs2(Root, Root);
    build(1, 1, N);
    while (Q--) {
    	int opt, x, y, z;
    	cin >> opt;
    	if (opt == 1) {
    		cin >> x >> y >> z;
    		RangeUpdate(x, y, z);
    	} else if (opt == 2) {
    		cin >> x >> y;
    		cout << RangeQuery(x, y) << endl;
    	} else if (opt == 3) {
    		cin >> x >> y;
    		SonUpdate(x, y);
    	} else {
    		cin >> x;
    		cout << SonQuery(x) << endl;
    	}
    }
	return 0;
}
2020/8/29 11:43
加载中...