题目大意:一棵树,支持三个操作,

$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]树的统计的更多相关文章

  1. 洛谷——P2590 [ZJOI2008]树的统计(树链剖分模板练手)

    P2590 [ZJOI2008]树的统计 I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问 ...

  2. 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]

    题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...

  3. 洛谷P2590 [ZJOI2008]树的统计 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2590 树链剖分模板题. 剖分过程要用到如下7个值: fa[u]:u的父节点编号: dep[u]:u的深度: size[u]: ...

  4. 洛谷 P2590 [ZJOI2008]树的统计(树链剖分)

    题目描述一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

  5. 洛谷 P2590 [ZJOI2008]树的统计

    大家好,我非常喜欢暴力数据结构,于是我用块状树过了这道题目 题目: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE ...

  6. 洛谷——P2590 [ZJOI2008]树的统计

    https://www.luogu.org/problem/show?pid=2590#sub 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这 ...

  7. 洛谷.2590.[ZJOI2008]树的统计(树分块)

    题目链接 Update:这种分块写法...可以被卡掉啊... 好像没有靠谱的树分块写法... /* 对树上节点进行分块,每个点记录dep,fa,val,Max,Sum,Max,Sum表示当前点在该块内 ...

  8. P2590 [ZJOI2008]树的统计(树链剖分)

    P2590 [ZJOI2008]树的统计 虽然是入门树剖模板 但是我终于1A了(大哭) 懒得写啥了(逃 #include<iostream> #include<cstdio> ...

  9. P2590 [ZJOI2008]树的统计(LCT)

    P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...

随机推荐

  1. U盘被分区后恢复方法

    一:运行cmd 二:输入diskpart,按enter. 三:输入list disk,按enter. 四:选择优U盘,输入select disk X(X代表磁盘后面的数字0.1,可磁盘的大小来判断数字 ...

  2. Java基础——继承和多态

    面向对象的编程允许从已经存在的类中定义新的类,这称为继承. 面向过程的范式重点在于方法的设计,而面向对象的范式将数据和方法结合在对象中.面向对象范式的软件设计着重于对象以及对象上的操作.面向对象的方法 ...

  3. 素数环 南阳acm488(回溯法)

    素数环 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环. 为了简 ...

  4. count_char

    import java.util.Scanner; public class count_char { public static void main(String args[]) { int cou ...

  5. 【转载】[Elasticsearch]ES入门

    传送门:http://www.cnblogs.com/xing901022 ES即简单又复杂,你可以快速的实现全文检索,又需要了解复杂的REST API.本篇就通过一些简单的搜索命令,帮助你理解ES的 ...

  6. C++11中decltype的使用

    The decltype type specifier yields the type of a specified expression. The decltype type specifier, ...

  7. Andrid 打印调用堆栈

    public static void printCallStatck() { Throwable ex = new Throwable(); StackTraceElement[] stackElem ...

  8. C#窗口抖动

    用过QQ的窗口抖动功能吧.是不是觉得很神奇?很有意思?其实,仔细想想,使用的原理还是挺简单的:让窗口的位置不断快速地发生变化. 说出了原理,是不是一下恍然大悟?顿时理解了.我以前也想过如何实现这个功能 ...

  9. c#根据ip获取城市地址

    用的API是百度.新浪.淘宝: 1.首先是一个检测获取的值是不是中文的方法,因为有的ip只能识别出来某省,而城市名称则为空返回的json里会出现null或undefined. public stati ...

  10. 使用JDK自带的keytool工具生成证书

    一.keytool 简介 keytool 是java用于管理密钥和证书的工具,它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及 ...