首页 > 代码库 > Light 1348 - Aladdin and the Return Journey(树链剖分)

Light 1348 - Aladdin and the Return Journey(树链剖分)

Light 1348 - Aladdin and the Return Journey

题目链接

树链剖分基础题,注意一个坑点,就是下标按0开始的话按我的写法是会错的,因为son初值赋成0了,要么改一下son初值,要么把下标都+1

代码:

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

const int N = 30005;

int dep[N], fa[N], son[N], sz[N], top[N], id[N], idx;
int first[N], next[N * 2], vv[N * 2];

void dfs1(int u, int f, int d) {
	dep[u] = d;
	sz[u] = 1;
	fa[u] = f;
	son[u] = 0;
	for (int i = first[u]; i + 1; i = next[i]) {
		int v = vv[i];
		if (v == f) continue;
		dfs1(v, u, d + 1);
		sz[u] += sz[v];
		if (sz[son[u]] < sz[v])
			son[u] = v;
	}
}

void dfs2(int u, int tp) {
	id[u] = ++idx;
	top[u] = tp;
	if (son[u]) dfs2(son[u], tp);
	for (int i = first[u]; i + 1; i = next[i]) {
		int v = vv[i];
		if (v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
}

inline int lowbit(int x) {
	return x&(-x);
}

int bit[N];

void add(int x, int v) {
	while (x < N) {
		bit[x] += v;
		x += lowbit(x);
	}
}

int get(int x) {
	int ans = 0;
	while (x) {
		ans += bit[x];
		x -= lowbit(x);
	}
	return ans;
}

int get(int l, int r) {
	return get(r) - get(l - 1);
}

int gao(int u, int v) {
	int tp1 = top[u], tp2 = top[v];
	int ans = 0;
	while (tp1 != tp2) {
		if (dep[tp1] < dep[tp2]) {
			swap(tp1, tp2);
			swap(u, v);
		}
		ans += get(id[tp1], id[u]);
		u = fa[tp1];
		tp1 = top[u];
	}
	if (dep[u] > dep[v]) swap(u, v);
	ans += get(id[u], id[v]);
	return ans;
}

int en;

void add_Edge(int u, int v) {
	vv[en] = v;
	next[en] = first[u];
	first[u] = en++;
}

int t, n, val[N];

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		idx = 0;
		en = 0;
		memset(bit, 0, sizeof(bit));
		memset(first, -1, sizeof(first));
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) scanf("%d", &val[i]);
		int u, v;
		for (int i = 1; i < n; i++) {
			scanf("%d%d", &u, &v);
			u++; v++;
			add_Edge(u, v);
			add_Edge(v, u);
		}
		dfs1(1, 0, 1);
		dfs2(1, 1);
		for (int i = 1; i <= n; i++)
			add(id[i], val[i]);
		int q;
		scanf("%d", &q);
		int ty, a, b;
		printf("Case %d:\n", ++cas);
		while (q--) {
			scanf("%d%d%d", &ty, &a, &b);
			if (ty) {
				a++;
				add(id[a], b - val[a]);
				val[a] = b;
			} else printf("%d\n", gao(a + 1, b + 1));
		}
	}
	return 0;
}


Light 1348 - Aladdin and the Return Journey(树链剖分)