树链剖分模板题
我感觉就是线段树+LCA的思想了
核心还是线段树
需要注意
在标记中,一个节点的所有子孙一定都是标号小于该节点的。
https://www.luogu.com.cn/problem/P2590
洛谷例题
解答
功能变多了就会很长很长
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
vector<int>G[maxn];
int n;
void add(int x, int y) {
G[x].push_back(y);
}
int dep[maxn], top[maxn], id[maxn], fa[maxn], siz[maxn];
int son[maxn];
ll list[maxn];//初始编号
ll cns[maxn];//改动后用来建线段树的编号
ll sum[4 * maxn];//求和
ll mx[4 * maxn];
int dfs1(int x, int f,int d) {
dep[x] = d;
fa[x] = f;
siz[x] = 1;
int s = 0;
for (int i = 0; i < G[x].size(); i++) {
int p = G[x][i];
if (p == f) continue;
dfs1(p, x, d + 1);
siz[x] += siz[p];
if (s < siz[p]) {
s = siz[p];
son[x] = p;
}
}
return 0;
}//haah
int cnt;
int dfs2(int x,int t) {
id[x] = ++cnt;
cns[cnt] = list[x];
top[x] = t;
if (!son[x]) return 0;
dfs2(son[x], t);//重儿子重复利用t
for (int i = 0; i < G[x].size();i++) {
int p = G[x][i];
if (p == fa[x] || p == son[x]) continue;
dfs2(p, p);//轻儿子新建t
}
return 0;
}
int bulit(int node, int be, int en) {
if (be == en) {
mx[node] = cns[be];
sum[node] = cns[be];
return 0;
}
int l = node * 2;
int r = node * 2 + 1;
int mid = (be + en) / 2;
bulit(l, be, mid);
bulit(r, mid + 1, en);
sum[node] = sum[l] + sum[r];
mx[node] = max(mx[l], mx[r]);
return 0;
}
int update(int node, int be, int en, int i, int val) {
if (be == en) {
sum[node] = val;
mx[node] = val;
return 0;
}
int l = node * 2;
int r = node * 2 + 1;
int mid = (be + en) / 2;
if (i <= mid) update(l, be, mid, i, val);
else update(r, mid + 1, en, i, val);
sum[node] = sum[l] + sum[r];
mx[node] = max(mx[l], mx[r]);
return 0;
}
ll qurry_sum(int node, int be, int en, int LL, int RR) {
if (LL > en || RR < be) return 0;
if (LL <= be && RR >= en) {
return sum[node];
}
int l = node * 2;
int r = node * 2 + 1;
int mid = (be + en) / 2;
ll val1 = qurry_sum(l, be, mid, LL, RR);
ll val2 = qurry_sum(r, mid + 1, en, LL, RR);
return val1 + val2;
}
ll qurry_max(int node, int be, int en, int LL, int RR) {
if (LL > en || RR < be) return -1e10;
if (LL <= be && en <= RR) {
return mx[node];
}
int l = node * 2;
int r = node * 2 + 1;
int mid = (be + en) / 2;
ll val1 = qurry_max(l, be, mid, LL, RR);
ll val2 = qurry_max(r, mid + 1, en, LL, RR);
return max(val1, val2);
}
ll qrank_max(int x, int y) {
ll ans = -1e18;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ll cns = qurry_max(1, 1, n, id[top[x]], id[x]);
ans = max(ans, cns);
x = fa[top[x]];
}
//现在两个点在一个重链上了
if (dep[x] > dep[y]) swap(x, y);
//x现在在y上面,id更小
ll cns = qurry_max(1, 1, n, id[x], id[y]);//注意顺序
ans = max(ans, cns);
return ans;
}
ll qrank_sum(int x, int y) {
ll ans = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ll cns = qurry_sum(1, 1, n, id[top[x]], id[x]);
ans += cns;
x = fa[top[x]];
}
//现在两个点在一个重链上了
if (dep[x] > dep[y]) swap(x, y);
//x现在在y上面,id更小
ll cns = qurry_sum(1, 1, n, id[x], id[y]);//注意顺序
ans += cns;
return ans;
}
char op[20];
int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
for (int i = 1; i <= n; i++) {
scanf("%lld", &list[i]);
}
dfs1(1, -1, 0);
dfs2(1, 1);
bulit(1, 1, n);
int q;
scanf("%d", &q);
while (q--) {
int x, y;
scanf("%s", op);
scanf("%d %d", &x, &y);
ll ans = 0;
if (op[1] == 'H') {
update(1, 1, n, id[x], y);
}
else if (op[1] == 'M') {
ans = qrank_max(x, y);
printf("%lld\n", ans);
}
else if (op[1] == 'S') {
ans = qrank_sum(x, y);
printf("%lld\n", ans);
}
}
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号