[洛谷P2590][ZJOI2008]树的统计
题目大意:一棵树,支持三个操作,
$CHANGE\;u\;t:$ 把结点$u$的权值改为$t$
$QMAX\;u\;v:$ 询问从点$u$到点$v$的路径上的节点的最大权值
$QSUM\;u\;v:$ 询问从点$u$到点$v$的路径上的节点的权值和
题解:裸的树链剖分
卡点:线段树区间修改我不知道哪根筋搭错了,写了$l\;==\;r$(应为$L\;\leq\;l\;\&\&\;R\;\geq\;r$)
C++ Code:
#include <cstdio>
#define maxn 30010
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m;
int w[maxn], V[maxn << 2], M[maxn << 2];
inline int max(int a, int b) {return a > b ? a : b;}
void swap(int &a, int &b) {a ^= b ^= a ^= b;}
void update(int rt) {
V[rt] = V[rt << 1] + V[rt << 1 | 1];
M[rt] = max(M[rt << 1], M[rt << 1 | 1]);
}
void build(int rt, int l, int r) {
if (l == r) {
V[rt] = M[rt] = w[l];
return ;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
update(rt);
}
void add(int rt, int l, int r, int p, int num) {
if (l == r) {
V[rt] = M[rt] = num;
return ;
}
int mid = l + r >> 1;
if (p <= mid) add(rt << 1, l, mid, p, num);
else add(rt << 1 | 1, mid + 1, r, p, num);
update(rt);
}
int askS(int rt, int l, int r, int L, int R) {
if (L <= l && R >= r) {
return V[rt];
}
int mid = l + r >> 1, ans = 0;
if (L <= mid) ans = askS(rt << 1, l, mid, L, R);
if (R > mid) ans = ans + askS(rt << 1 | 1, mid + 1, r, L, R);
return ans;
}
int askM(int rt, int l, int r, int L, int R) {
if (L <= l && R >= r) {
return M[rt];
}
int mid = l + r >> 1, ans = -inf;
if (L <= mid) ans = askM(rt << 1, l, mid, L, R);
if (R > mid) ans = max(ans, askM(rt << 1 | 1, mid + 1, r, L, R));
return ans;
} int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
void addE(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
}
int fa[maxn], sz[maxn], son[maxn], dep[maxn];
int top[maxn], dfn[maxn], idx;
void dfs1(int rt) {
sz[rt] = 1;
for (int i = head[rt]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[rt]) {
dep[v] = dep[rt] + 1;
fa[v] = rt;
dfs1(v);
if (!son[rt] || sz[v] > sz[son[rt]]) son[rt] = v;
sz[rt] += sz[v];
}
}
}
void dfs2(int rt) {
dfn[rt] = ++idx;
int v = son[rt];
if (v) top[v] = top[rt], dfs2(v);
for (int i = head[rt]; i; i = e[i].nxt) {
v = e[i].to;
if (v != son[rt] && v != fa[rt]) {
top[v] = v;
dfs2(v);
}
}
}
int queryS(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += askS(1, 1, n, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans += askS(1, 1, n, dfn[x], dfn[y]);
return ans;
}
int queryM(int x, int y) {
int ans = -inf;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, askM(1, 1, n, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans = max(ans, askM(1, 1, n, dfn[x], dfn[y]));
return ans;
}
int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
addE(a, b);
addE(b, a);
}
dep[1] = 1;
dfs1(1);
top[1] = 1;
dfs2(1);
for (int i = 1; i <= n; i++) {
scanf("%d", &w[dfn[i]]);
}
build(1, 1, n);
scanf("%d", &m);
while (m --> 0) {
char op[10];
int x, y;
scanf("%s%d%d", op, &x, &y);
if (op[1] == 'M') {
printf("%d\n", queryM(x, y));
}
if (op[1] == 'S') {
printf("%d\n", queryS(x, y));
}
if (op[1] == 'H') {
add(1, 1, n, dfn[x], y);
}
}
return 0;
}
[洛谷P2590][ZJOI2008]树的统计的更多相关文章
- 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)
P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...
- 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]
题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...
- 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...
- 洛谷 P2590 [ZJOI2008]树的统计(树链剖分)
题目描述一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
- 洛谷 P2590 [ZJOI2008]树的统计
大家好,我非常喜欢暴力数据结构,于是我用块状树过了这道题目 题目: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE ...
- 洛谷——P2590 [ZJOI2008]树的统计
https://www.luogu.org/problem/show?pid=2590#sub 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这 ...
- 洛谷.2590.[ZJOI2008]树的统计(树分块)
题目链接 Update:这种分块写法...可以被卡掉啊... 好像没有靠谱的树分块写法... /* 对树上节点进行分块,每个点记录dep,fa,val,Max,Sum,Max,Sum表示当前点在该块内 ...
- P2590 [ZJOI2008]树的统计(树链剖分)
P2590 [ZJOI2008]树的统计 虽然是入门树剖模板 但是我终于1A了(大哭) 懒得写啥了(逃 #include<iostream> #include<cstdio> ...
- P2590 [ZJOI2008]树的统计(LCT)
P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...
随机推荐
- jsonp 跨域只能调用一次ajax(无法多次调用或者循环调用)
jsonp 跨域只能掉用一次ajax(无法多次调用或者循环调用) 百度搜索关键字:jsonp 只能调用一次ajax 解决方法 //回调函数设置,给后台执行 window[callback ...
- thinkphp5数据库导入Excel表格
$data=$order_info; //$data 你要下载谁 就去查谁 // $data= Db::name('order_info') // ->field('consignee,tel, ...
- 链栈的c++实现
2013-08-30 20:58 1876人阅读 评论(0) 收藏 举报 链栈是借用单链表实现的栈.其不同于顺序栈之处在于: 1.链栈的空间是程序运行期间根据需要动态分配的,机器内存是它的上限.而顺序 ...
- R语言学习笔记(十五):获取文件和目录信息
file.info() 参数是表示文件名称的字符串向量,函数会给出每个文件的大小.创建时间.是否为目录等信息. > file.info("z.txt") size isdir ...
- ABS(引数と同じ大きさの正の数を返す)
ABS 関数 [数値] 数値式の絶対値を返します. 構文 ABS( numeric-expression ) パラメータ numeric-expression 絶対値が返される数値. 戻り値 数値 ...
- List排序方法
可用使用Collections.sort(List<T> list)和Collections.sort(List<T> list, Comparator<? super ...
- 教你Zbrush 4R7怎样创建Z球
随着CG行业的迅猛发展,就业门槛大幅度提高,对于从业人员要求就是要“又快又好”,作为一个模型师,常会碰到一天或两天完成一个全身角色的考题,而且还需要角度摆出造型,以前做这个的话,可能比较难,现在有了Z ...
- Markdown 基本用法
声明:引自 http://www.cnblogs.com/hnrainll/p/3514637.html ,感谢! 1. 标题设置(让字体变大,和word的标题意思一样)在Markdown当中设置 ...
- Develop Android Game Using Cocos2d-x
0. Environment Windows 7 x64Visual Studio 2013adt-bundle-windows-x86 (http://developer.android.com/s ...
- 第三十篇 面向对象的三大特性之继承 supre()
继承 一 .什么是继承? 类的继承跟现实生活中的父.子.孙子.重孙子的继承关系一样,父类又称基类. Python中类的继承分为:单继承 和 多继承. # 定义父类 class ParentClass ...