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

$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. jsonp 跨域只能调用一次ajax(无法多次调用或者循环调用)

    jsonp 跨域只能掉用一次ajax(无法多次调用或者循环调用) 百度搜索关键字:jsonp 只能调用一次ajax 解决方法 //回调函数设置,给后台执行        window[callback ...

  2. thinkphp5数据库导入Excel表格

    $data=$order_info; //$data 你要下载谁 就去查谁 // $data= Db::name('order_info') // ->field('consignee,tel, ...

  3. 链栈的c++实现

    2013-08-30 20:58 1876人阅读 评论(0) 收藏 举报 链栈是借用单链表实现的栈.其不同于顺序栈之处在于: 1.链栈的空间是程序运行期间根据需要动态分配的,机器内存是它的上限.而顺序 ...

  4. R语言学习笔记(十五):获取文件和目录信息

    file.info() 参数是表示文件名称的字符串向量,函数会给出每个文件的大小.创建时间.是否为目录等信息. > file.info("z.txt") size isdir ...

  5. ABS(引数と同じ大きさの正の数を返す)

    ABS 関数 [数値] 数値式の絶対値を返します. 構文 ABS( numeric-expression ) パラメータ numeric-expression   絶対値が返される数値. 戻り値 数値 ...

  6. List排序方法

    可用使用Collections.sort(List<T> list)和Collections.sort(List<T> list, Comparator<? super ...

  7. 教你Zbrush 4R7怎样创建Z球

    随着CG行业的迅猛发展,就业门槛大幅度提高,对于从业人员要求就是要“又快又好”,作为一个模型师,常会碰到一天或两天完成一个全身角色的考题,而且还需要角度摆出造型,以前做这个的话,可能比较难,现在有了Z ...

  8. Markdown 基本用法

    声明:引自 http://www.cnblogs.com/hnrainll/p/3514637.html ,感谢!   1. 标题设置(让字体变大,和word的标题意思一样)在Markdown当中设置 ...

  9. Develop Android Game Using Cocos2d-x

    0. Environment Windows 7 x64Visual Studio 2013adt-bundle-windows-x86 (http://developer.android.com/s ...

  10. 第三十篇 面向对象的三大特性之继承 supre()

    继承 一 .什么是继承? 类的继承跟现实生活中的父.子.孙子.重孙子的继承关系一样,父类又称基类. Python中类的继承分为:单继承 和  多继承. # 定义父类 class ParentClass ...