[洛谷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 : 把 ...
随机推荐
- 判断不同浏览器,加载不同的css和js文件
在低版本的IE中,条件注释还有效果,但是在ie9,10,11浏览器中,条件注释不起作用. 在网上找了个校验ie的方法. function isIE(){ if (window.ActiveXObje ...
- Python自动化运维——系统进程管理模块
Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:psutil psutil是一个跨平台库,可以很轻松的为我们实现获取系统运行的进程和资源利用率等信息. 功能 ...
- JAVA学习一 对象数组
对象数组 今天在写一个代码,才发现自己对于对象数组的理解是不够的,那么就讲讲自己现在的理解. 对于数组中的每一个元素都是一个针对对象的引用 他会指向你的具体的一个堆上的对象,它本身知识一个地址值,与其 ...
- 45-Identity MVC:注册逻辑实现
1-注册页Register.cshtml <h3>Register</h3> @model MvcCookieAuthSample.ViewModel.RegisterView ...
- ionic打包apkFailed to execute shell command "input,keyevent,82"" on device: Error: adb: Command failed with exit code 137
错误代码如下 BUILD SUCCESSFUL in 12s 46 actionable tasks: 1 executed, 45 up-to-date Built the following ap ...
- PIC24 通过USB在线升级 -- USB CDC bootloader
了解bootloader的实现,请加QQ: 1273623966 (验证填bootloader):欢迎咨询或定制bootloader:我的博客主页www.cnblogs.com/geekygeek 今 ...
- 自定义T4模板去掉实体对象中的下划线
在EF Power Tool 默认使用的T4模板中,如果数据库表有下划线,那么生成的实体也有下划线,但是我们实际使用的过程中,是不希望有下划线的,要解决这个问题,可以自定义这个T4模板 ...
- 使用JDK自带的keytool工具生成证书
一.keytool 简介 keytool 是java用于管理密钥和证书的工具,它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及 ...
- Leetcode代码补全——链表
通过补全代码可以更深刻的体会到,链表就是一个存储方式,通过一单元的存储指向下一单元,而查看单元内容通过头部开始的指针依次遍历.这是leetcode里融合两个链表的题目,具体代码如下: #encodin ...
- 监控memcache服务
监控memcache服务是否正常,模拟用户(web客户端)检测. 使用nc命令加上set/get来模拟检测,以及监控响应时间及命中率. #!/bin/bash #################### ...