题目链接:https://www.luogu.org/problem/P2590

树链剖分模板题。

剖分过程要用到如下7个值:

  • fa[u]:u的父节点编号;
  • dep[u]:u的深度;
  • size[u]:u为根的子树中节点总数;
  • son[u]:u的重儿子;
  • top[u]:u所在的重链的顶部节点;
  • seg[u]:u在线段树中的位置;
  • rev[u]:seg的倒置,即rev[seg[u]] == u

然后套线段树模板实现区间最值、区间和,及单点更新操作。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
#define INF (1<<29)
const int maxn = 30030;
int fa[maxn],
dep[maxn],
size[maxn],
son[maxn],
top[maxn],
seg[maxn], seg_cnt,
rev[maxn],
n, w[maxn], maxv[maxn<<2], sumv[maxn<<2];
vector<int> g[maxn];
void dfs1(int u, int p) {
size[u] = 1;
for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
int v = (*it);
if (v == p) continue;
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v, u);
size[u] += size[v];
if (size[v] >size[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
seg[u] = ++seg_cnt;
rev[seg_cnt] = u;
top[u] = tp;
if (son[u]) dfs2(son[u], tp);
for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it ++) {
int v = (*it);
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
void push_up(int rt) {
sumv[rt] = sumv[rt<<1] +sumv[rt<<1|1];
maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);
}
void build(int l, int r, int rt) {
int mid = (l + r) / 2;
if (l == r) {
sumv[rt] = maxv[rt] = w[rev[l]];
return;
}
build(lson); build(rson);
push_up(rt);
}
void update(int p, int v, int l, int r, int rt) {
if (l == r) {
sumv[rt] = maxv[rt] = v;
return;
}
int mid = (l + r) / 2;
if (p <= mid) update(p, v, lson);
else update(p, v, rson);
push_up(rt);
}
int query_max(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return maxv[rt];
int mid = (l + r) / 2, tmp = -INF;
if (L <= mid) tmp = max(tmp, query_max(L, R, lson));
if (R > mid) tmp = max(tmp, query_max(L, R, rson));
return tmp;
}
int query_sum(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return sumv[rt];
int mid = (l + r) / 2, tmp = 0;
if (L <= mid) tmp += query_sum(L, R, lson);
if (R > mid) tmp += query_sum(L, R, rson);
return tmp;
}
int ask_max(int u, int v) {
int res = -INF;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
res = max(res, query_max(seg[top[u]], seg[u], 1, n, 1));
u = fa[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
res = max(res, query_max(seg[v], seg[u], 1, n, 1));
return res;
}
int ask_sum(int u, int v) {
int res = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
res += query_sum(seg[top[u]], seg[u], 1, n, 1);
u = fa[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
res += query_sum(seg[v], seg[u], 1, n, 1);
return res;
}
int m;
string s;
int main() {
cin >> n;
for (int i = 1; i < n; i ++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= n; i ++) cin >> w[i];
dep[1] = fa[1] = 1;
dfs1(1, -1);
dfs2(1, 1);
build(1, n, 1);
cin >> m;
while (m --) {
int u, v;
cin >> s >> u >> v;
if (s == "CHANGE") update(seg[u], v, 1, n, 1);
else if (s == "QMAX") cout << ask_max(u, v) << endl;
else cout << ask_sum(u, v) << endl;
}
return 0;
}

最新文章

  1. Undefined symbols for architecture arm64:
  2. java22
  3. 文件大小K、M、G、T
  4. Quartus 的管脚分配
  5. QQ Auto Login Visual Basic Script
  6. Python 虚拟环境Virtualenv
  7. Asp.net MVC中Route的理解
  8. String类、正则表达式
  9. d3.js &lt;一&gt;
  10. linux如何关闭selinux?
  11. 插件 - 提示窗体(ArtDialog)
  12. Portal.MVC
  13. MySQL in不走索引
  14. elasticsearch报错expected &lt;block end&gt;, but found BlockMappingStart解决方法
  15. Ubunttu16.04升级/更新git版本(亲测有效)
  16. jeecg富文本编辑器增加字体(仿宋)
  17. Python学习第五堂课
  18. 现代php编程
  19. 广商博客沖刺第一天(new ver):
  20. 自学Linux Shell6.2-用户自定义环境变量

热门文章

  1. shared_from_this bad_weak_ptr的原因
  2. html DOM(CSS放置位置的问题)
  3. Poj 2104区间第k大(归并树)
  4. PHP定时任务获取微信access_token的方法
  5. JQuery-- 链式编程、静态函数,自己制作jQuery插件
  6. RapidMiner Studio 入门
  7. 阿里OSS-OSSFS
  8. Python Unittest根据不同测试环境跳过用例详解
  9. oralce MTS
  10. 网络流24题 骑士共存(DCOJ8023)