题目链接

题意: I. CHANGE u t : 把结点u的权值改为t

   II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

   III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

分析:树链剖分第一题,把树拆成一条条链,有重链和轻链,每个点有转换后的新的位置,同一条链是线性的区间,这样可以用线段树进行操作。第一个是单点更新,第二个先求LCA,然后把u和v移动到lca所在的链,转移一次都是转移链,区间询问最大值和总和,第三种类似。

#include <bits/stdc++.h>

const int N = 3e4 + 5;
const int D = 20;
const int INF = 0x7fffffff;
struct Edge {
int v, nex;
}edge[N<<1];
int head[N];
int a[N];
int sz[N], dep[N], belong[N], pos[N];
int rt[N][D];
int n, tote, loc; void add_edge(int u, int v) {
edge[tote].v = v; edge[tote].nex = head[u];
head[u] = tote++;
} void init_edge() {
memset (head, -1, sizeof (head));
tote = 0;
} void DFS1(int u, int fa) {
sz[u] = 1; dep[u] = dep[fa] + 1;
rt[u][0] = fa;
for (int i=head[u]; ~i; i=edge[i].nex) {
int v = edge[i].v;
if (v == fa) {
continue;
}
DFS1 (v, u);
sz[u] += sz[v];
}
} void DFS2(int u, int fa, int chain) {
int k = 0;
pos[u] = ++loc;
belong[u] = chain;
for (int i=head[u]; ~i; i=edge[i].nex) {
int v = edge[i].v;
if (v == fa) {
continue;
}
if (sz[v] > sz[k]) {
k = v;
}
}
if (k == 0) {
return ;
}
DFS2 (k, u, chain);
for (int i=head[u]; ~i; i=edge[i].nex) {
int v = edge[i].v;
if (v == fa || v == k) {
continue;
}
DFS2 (v, u, v);
}
} void init_LCA() {
for (int j=1; j<D; ++j) {
for (int i=1; i<=n; ++i) {
rt[i][j] = rt[i][j-1] == 0 ? 0 : rt[rt[i][j-1]][j-1];
}
}
} int LCA(int u, int v) {
if (dep[u] < dep[v]) {
std::swap (u, v);
}
for (int i=0; i<D; ++i) {
if ((dep[u] - dep[v]) >> i & 1) {
u = rt[u][i];
}
}
if (u == v) {
return u;
}
for (int i=D-1; i>=0; --i) {
if (rt[u][i] != rt[v][i]) {
u = rt[u][i];
v = rt[v][i];
}
}
return rt[u][0];
} int mx[N<<2], sum[N<<2]; #define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1 void push_up(int o) {
mx[o] = std::max (mx[o<<1], mx[o<<1|1]);
sum[o] = sum[o<<1] + sum[o<<1|1];
} void updata(int p, int v, int l, int r, int o) {
if (l == r) {
mx[o] = sum[o] = v;
return ;
}
int mid = l + r >> 1;
if (p <= mid) {
updata (p, v, lson);
} else {
updata (p, v, rson);
}
push_up (o);
} int query_max(int ql, int qr, int l, int r, int o) {
if (ql <= l && r <= qr) {
return mx[o];
}
int mid = l + r >> 1, ret = -INF;
if (ql <= mid) {
ret = std::max (ret, query_max (ql, qr, lson));
}
if (qr > mid) {
ret = std::max (ret, query_max (ql, qr, rson));
}
return ret;
} int query_sum(int ql, int qr, int l, int r, int o) {
if (ql <= l && r <= qr) {
return sum[o];
}
int mid = l + r >> 1, ret = 0;
if (ql <= mid) {
ret += query_sum (ql, qr, lson);
}
if (qr > mid) {
ret += query_sum (ql, qr, rson);
}
return ret;
} int get_sum(int u, int lca) {
int ret = 0;
while (belong[u] != belong[lca]) {
ret += query_sum (pos[belong[u]], pos[u], 1, n, 1);
u = rt[belong[u]][0];
}
ret += query_sum (pos[lca], pos[u], 1, n, 1);
return ret;
} int get_max(int u, int lca) {
int ret = -INF;
while (belong[u] != belong[lca]) {
ret = std::max (ret, query_max (pos[belong[u]], pos[u], 1, n, 1));
u = rt[belong[u]][0];
}
ret = std::max (ret, query_max (pos[lca], pos[u], 1, n, 1));
return ret;
} void prepare() {
sz[0] = 0; dep[0] = 0;
DFS1 (1, 0);
loc = 0;
DFS2 (1, 0, 1);
init_LCA ();
for (int i=1; i<=n; ++i) {
updata (pos[i], a[i], 1, n, 1);
}
} int main() {
scanf ("%d", &n);
init_edge ();
for (int i=1; i<n; ++i) {
int u, v;
scanf ("%d%d", &u, &v);
add_edge (u, v);
add_edge (v, u);
}
for (int i=1; i<=n; ++i) {
scanf ("%d", a+i);
} prepare (); int q;
scanf ("%d", &q);
char ch[6];
int x, y;
while (q--) {
scanf ("%s%d%d", ch, &x, &y);
if (ch[0] == 'C') {
a[x] = y;
updata (pos[x], a[x], 1, n, 1);
} else {
int lca = LCA (x, y);
if (ch[1] == 'M') {
printf ("%d\n", std::max (get_max (x, lca), get_max (y, lca)));
} else {
printf ("%d\n", get_sum (x, lca) + get_sum (y, lca) - a[lca]);
}
}
}
return 0;
}

  

树链剖分+线段树 BZOJ 1036 [ZJOI2008]树的统计Count的更多相关文章

  1. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  2. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  3. 【bzoj1036】树的统计[ZJOI2008]树链剖分+线段树

    题目传送门:1036: [ZJOI2008]树的统计Count 这道题是我第一次打树剖的板子,虽然代码有点长,但是“打起来很爽”,而且整道题只花了不到1.5h+,还是一遍过样例!一次提交AC!(难道前 ...

  4. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  5. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  6. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  7. bzoj 2157: 旅游【树链剖分+线段树】

    裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...

  8. BZOJ 3589 动态树 (树链剖分+线段树)

    前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...

  9. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  10. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

随机推荐

  1. jQuery5~7章笔记 和 1~3章的复习笔记

    JQery-05 对表单和表格的操作及其的应用 JQery-06 jQuery和ajax的应用 JQery-07 jQuery插件的使用和写法 JQery-01-03 复习 之前手写的笔记.实在懒得再 ...

  2. [NHibernate]一对多关系(级联删除,级联添加)

    目录 写在前面 文档与系列文章 一对多关系 一个例子 级联删除 级联保存 总结 写在前面 在前面的文章中,我们只使用了一个Customer类进行举例,而在客户.订单.产品中它们的关系,咱们并没有涉及, ...

  3. [译] 你该知道的javascript作用域 (javascript scope)(转)

    javascript有一些对于初学者甚至是有经验的开发者都难以理解的概念. 这个部分是针对那些听到 : 作用域, 闭包, this, 命名空间, 函数作用域, 函数作用域, 全局作用域, 变量作用域( ...

  4. VTK初学一,比较常见的错误2

    我的开发环境: 系统:win8.1 QT:5.4.2MinGW版 VTK:6.3 按照教程生成一个球体显示在,Qt的QVTKWidget控件中,出现如下ERROR: ERROR: In D:\VTK6 ...

  5. Excel函数——DATE、SUBSTITUTE、REPLACE、ISERROR、IFERROR

    1.DATE DATE 函数返回表示特定日期的连续序列号.例如,公式 =DATE(2008,7,8) 返回 2008-7-8或39637,取决于单元格格式,但空单元格计算和默认为日期格式. DATE也 ...

  6. (转载)JavaWeb学习总结(五十三)——Web应用中使用JavaMail发送邮件

    博客源地址:http://www.cnblogs.com/xdp-gacl/p/4220190.html 现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件.邮件 ...

  7. PHP定时备份MySQL,mysqldump语法大全

    几个常用操作: 1.备份 # 只导出表结构 d:/PHP/xampp/mysql/bin/mysqldump -h127.0.0.1 -P3306 -uroot -p123456 snsgou_sns ...

  8. C和指针 第十章 结构和联合 习题

    1. 记账信息结构联合 typedef struct { unsigned int areaNum; unsigned int transNum; unsigned int station; } ph ...

  9. 在android程序中加入widget(窗口小部件)并与之交互的关键代码

    摘要: widget(窗口小部件)可以增强应用程序的交互性, 是很多应用中都会用到的功能,本文不求大而全,但是会给出程序与widget交互的关键代码 正文: 其实widget是嵌入(embedded) ...

  10. 批量删除 svn文件

    windows下批量删除SVN的方法 ============================ 在.svn的同级目录,也就是项目的根目录 新建文件 killsvn.bat 输入内容: @echo on ...