洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树
题目链接: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;
}
洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树的更多相关文章
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- 【bzoj1036】树的统计[ZJOI2008]树链剖分+线段树
题目传送门:1036: [ZJOI2008]树的统计Count 这道题是我第一次打树剖的板子,虽然代码有点长,但是“打起来很爽”,而且整道题只花了不到1.5h+,还是一遍过样例!一次提交AC!(难道前 ...
- 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树
正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
随机推荐
- LUOGU P1081 开车旅行 (noip 2012)
传送门 解题思路 这道题刚了一下午,主要就刚在set那里了.先写了一个暴力70分..之后优化预处理,看着大佬神犇们都用的什么双向链表之类的东西,本蒟蒻不会,又懒得手写平衡树,就拿了个set搞了搞,感觉 ...
- hack 记录
0.寻找信号强的wifi,对于隐藏ssid 的可通过嗅探 1.wifi密码:wifi万能钥匙.minidwep-gtk.aircrack-ng 2.对于绑定mac地址的安全设置,可通过对活动的客户端网 ...
- 安装 cx_Oracle
1.下载 oracle client instant 和 sdk, 全部解压到 /opt/instantclient_11_2/ http://www.oracle.com/technetwor ...
- DirectX11笔记(一)--配置DirectX工程
原文:DirectX11笔记(一)--配置DirectX工程 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737/article/d ...
- 【水滴石穿】rn_antd_dva_reactnavigation
这个项目好像就是记录了一个数据的流向,大体思想好像是这个 项目地址:https://github.com/Yangzhuren/rn_antd_dva_reactnavigation 先看效果 第一个 ...
- 【arduino】anroid的app与arduino的ch05,进行蓝牙通信遇到的问题
Arduino程序上传不成功 显示系统找不到指定文件 错误信息显示是 avrdude: ser_open(): can't open device "\\.\COM1": 系统找不 ...
- 【CF Manthan, Codefest 17 A】Tom Riddle's Diary
[链接]h在这里写链接 [题意] 在这里写题意 [题解] /* Be careful. 二重循环枚举 */ [错的次数] 0 [反思] 在这了写反思 [代码] #include <bits/st ...
- less知识点总结(一)
1.unit 删除或更换单位. 参数: dimension: 带单位或不带单位的数字. unit: (可选) 目标单位,如果省略此参数,则删除单位. See convert for changing ...
- 【Django入坑之路】Django与Query Ajax的交互
1:Jquery.ajax后端交互数据 $.ajax({ Url: /路由处理/, Type: GET/POST, #传送请求类型 Data: {user: “ XXXX”,pass:”XXXX”}, ...
- hdu1080 LCS变形
dp[i][j]表示配对的最大值. dp[i-1][j]表示s1[i-1]与'-'配对. dp[i][j-1]表示s2[j-1]与'-'配对. dp[i-1][j-1]表示s1[i-1]与s2[j-1 ...