最近几次考试多多少少都有所涉及树链剖分,所以做了一下总结,顺便练习了几道板子题
树链剖分的原理简介
树链剖分简单的来说,就是通过对一棵树进行编号,然后在线段树上解决树求最大值、和等问题
而树链剖分的编号一般是通过dfs进行遍历按照遍历的先后顺序记录dfs序(又叫时间戳)
树链剖分的模板基本上是大同小异的,关键是要多做题啊
考试时遇到的几个树链剖分
数据结构练习(T4)
【SPOJ375 QTREE】修铁路
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ls (x << 1)
#define rs (x << 1 | 1)
#define mid ((l + r) >> 1)
#define L 10000 + 10
using namespace std;
struct edge{
int next, to;
}e[L << 1];
int n, a, b, c;
int d[L][3], head[L << 1];
int fa[L], son[L], w[L], siz[L], dep[L], top[L];
int cnt = 0, tot = 1, tree[L << 2];
char str[20];
int max(int a, int b) {
return a > b ? a : b;
}
void add(int from, int to) {
e[++cnt].next = head[from];
e[cnt].to = to;
head[from] = cnt;
}
void dfs1(int now, int pre) {
fa[now] = pre;
siz[now] = 1;
son[now] = 0;
dep[now] = dep[pre] + 1;
for (int u = head[now]; u > 0; u = e[u].next) {
int v = e[u].to;
if (v != pre) {
dfs1(v, now);
siz[now] += siz[v];
if (siz[son[now]] < siz[v]) son[now] = v;
}
}
}
void dfs2(int now, int tp) {
w[now] = tot++;
top[now] = tp;
if (son[now]) dfs2(son[now], top[now]);
for (int u = head[now]; u > 0; u = e[u].next) {
int v = e[u].to;
if (fa[now] != v && son[now] != v) dfs2(v, v);
}
}
void updata(int x, int l, int r, int a, int v) {
if (l == r) {
tree[x] = v; return ;
}
if (a <= mid) updata(ls, l, mid, a, v);
if (a > mid) updata(rs, mid + 1, r, a, v);
tree[x] = max(tree[ls], tree[rs]);
}
int find(int x, int l, int r, int a, int b) {
if (a <= l && r <= b) return tree[x];
if (b <= mid) return find(ls, l, mid, a, b);
else if (a > mid) return find(rs, mid + 1, r, a, b);
else return max(find(ls, l, mid, a, mid), find(rs, mid + 1, r, mid + 1, b));
}
int solve(int a, int b) {
int f1 = top[a], f2 = top[b], temp = 0<