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

$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. C#中的线程(二)线程同步基础 (读后感)

    参考文章:https://www.cnblogs.com/dingfangbo/p/5769501.html 一.lock 确保只有一个线程访问某个资源或某段代码.通俗的讲就是多个线程操作相同的锁对象 ...

  2. symfony 安装使用(一)

    Symfony安装教程网上已经存在很多了,但是这里还是要写一下: 1.symfony 安装有以下几种,对应不同的环境 1.1通过composer 命令安装 composer create-projec ...

  3. print(__file__)返回<encoding error>的问题

    今天写了一下代码,本来是想得到当前文件的上面三层的目录的,结果返回的却是错误 import os import sys print(__file__) # 得到上上层目录的路径之后,加入到默认的环境变 ...

  4. Mult

    public class MULT { public static void main(String args[]) { int k; for(int x=1;x<=9;x++) { for(i ...

  5. PAT-B java实现

    注意:java提交PAT时,不需要加package : 类名必须是Main. 1001 害死人不偿命的(3n+1)猜想 (15) 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值. 输出格式 ...

  6. MVC使用ajax取得JSon数据

    为了在view中获取模型中的数据,用ajax异步模式读取数据,再用json返回的view中. 1.controller中: [HttpPost] public ActionResult GetAjax ...

  7. 听雷哥浅谈Redis

    Linux下安装redis 1.下载源码,解压缩后编译源码. $ wget http://download.redis.io/releases/redis-2.8.3.tar.gz $ tar xzf ...

  8. windows下oracle 11g r2 安装过程与卸载详细图解

    Oracle 11g安装 1.解压下载的包,然后进入包内,点击setup.exe开始安装 . 2.出现如下:一般把那个小对勾取消,点击下一步进行, 弹出下图这个后点‘是' 3.下图后,选择创建和配置数 ...

  9. asp.net 模拟CURL调用微信公共平台API 上传下载多媒体文件接口

    FormItem类 public class FormItem { public string Name { get; set; } public ParamType ParamType { get; ...

  10. 超强排序JavaScript插件

    Sortable:http://rubaxa.github.io/Sortable/