Luogu P2590 树的统计(树链剖分+线段树)
题意
原文很清楚了
题解
重链剖分模板题,用线段树维护即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::max;
using std::swap;
const int N = 3e4 + 10, Inf = 1e9 + 7;
int n, q, c[N], x, y;
int fa[N], dep[N], son[N], siz[N];
int top[N], w[N], dfn[N], time;
int cnt, from[N], to[N << 1], nxt[N << 1];//Edges;
int maxv[N << 2], sumv[N << 2];//SegTree
inline void addEdge(int u, int v) {
to[++cnt] = v, nxt[cnt] = from[u], from[u] = cnt;
}
void dfs1(int u) {
siz[u] = 1, dep[u] = dep[fa[u]] + 1;
for (int i = from[u]; i; i = nxt[i]) {
int v = to[i]; if(v == fa[u]) continue;
fa[v] = u, dfs1(v), siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int t) {
top[u] = t, dfn[u] = ++time, w[time] = c[u];
if(!son[u]) { return ; } dfs2(son[u], t);
for (int i = from[u]; i; i = nxt[i]) {
int v = to[i];
if (v != fa[u] && v != son[u])
dfs2(v, v);
}
}
void pushup (int o, int lc, int rc) {
sumv[o] = sumv[lc] + sumv[rc];
maxv[o] = max(maxv[lc], maxv[rc]);
}
void build(int o = 1, int l = 1, int r = n) {
if(l == r) { sumv[o] = maxv[o] = w[l]; return ; }
int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
build(lc, l, mid), build(rc, mid + 1, r), pushup(o, lc, rc);
}
void modify(int p, int k, int o = 1, int l = 1, int r = n) {
if(l == r && l == p) { sumv[o] = maxv[o] = k; return ; }
int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1;
if(p <= mid) modify(p, k, lc, l, mid);
else modify(p, k, rc, mid + 1, r);
pushup(o, lc, rc);
}
int quemax(int ql, int qr, int o = 1, int l = 1, int r = n) {
if(l >= ql && r <= qr) return maxv[o];
int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1, ret = -Inf;
if(ql <= mid) ret = quemax(ql, qr, lc, l, mid);
if(qr > mid) ret = max(ret, quemax(ql, qr, rc, mid + 1, r));
return ret;
}
int quesum(int ql, int qr, int o = 1, int l = 1, int r = n) {
if(l >= ql && r <= qr) return sumv[o];
int mid = (l + r) >> 1, lc = o << 1, rc = lc | 1, ret = 0;
if(ql <= mid) ret = quesum(ql, qr, lc, l, mid);
if(qr > mid) ret += quesum(ql, qr, rc, mid + 1, r);
return ret;
}
int quem(int x, int y) {
int fx = top[x], fy = top[y], ret = -Inf;
while(fx != fy) {
if(dep[fx] >= dep[fy])
ret = max(ret, quemax(dfn[fx], dfn[x])), x = fa[fx], fx = top[x];
else
ret = max(ret, quemax(dfn[fy], dfn[y])), y = fa[fy], fy = top[y];
}
if(dfn[x] > dfn[y]) swap(x, y);
return max(ret, quemax(dfn[x], dfn[y]));
}
int ques(int x, int y) {
int fx = top[x], fy = top[y], ret = 0;
while(fx != fy) {
if(dep[fx] >= dep[fy])
ret += quesum(dfn[fx], dfn[x]), x = fa[fx], fx = top[x];
else
ret += quesum(dfn[fy], dfn[y]), y = fa[fy], fy = top[y];
}
if(dfn[x] > dfn[y]) swap(x, y);
return ret + quesum(dfn[x], dfn[y]);
}
int main () {
scanf("%d", &n);
for (int i = 1, u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
addEdge(u, v), addEdge(v, u);
}
for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);
dfs1(1), dfs2(1, 1);
build();
scanf("%d", &q);
char opt[10];
while(q--) {
scanf("\n%s %d %d", opt, &x, &y);
if(opt[0] == 'Q') {
if(opt[1] == 'M') printf("%d\n", quem(x, y));
else printf("%d\n", ques(x, y));
} else modify(dfn[x], y);
}
return 0;
}
Luogu P2590 树的统计(树链剖分+线段树)的更多相关文章
- BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- 【bzoj1036】树的统计[ZJOI2008]树链剖分+线段树
题目传送门:1036: [ZJOI2008]树的统计Count 这道题是我第一次打树剖的板子,虽然代码有点长,但是“打起来很爽”,而且整道题只花了不到1.5h+,还是一遍过样例!一次提交AC!(难道前 ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
随机推荐
- 2017 济南综合班 Day 1
送分题(songfen) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK喜欢干一些有挑战的事,比如说求区间最大子段和.它知道这个题目有O(n)的做法.于 ...
- C11性能之道:转移和转发
1.move C++11中可以将左值强制转换为右值,从而避免对象的拷贝来提升性能.move将对象的状态或者所有权从一个对象转移到另一个对象,没有内存拷贝.深拷贝和move的区别如图: 从图可以看出,深 ...
- 【BZOJ】1731: [Usaco2005 dec]Layout 排队布局
[题意]给定按编号顺序站成一排的牛,给定一些约束条件如两牛距离不小于或不大于某个值,求1和n的最大距离.无解输出-1,无穷解输出-2. [算法]差分约束+最短路 [题解]图中有三个约束条件,依次分析: ...
- 【洛谷 P5110】 块速递推(矩阵加速,分块打表)
题目链接 掌握了分块打表法了.原来以前一直想错了... 块的大小\(size=\sqrt n\),每隔\(size\)个数打一个表,还要在\(0\text{~}size-1\)每个数打一个表. 然后就 ...
- this的九种常用场景(转子jb51.net)
[场景1]全局环境中的this指向全局对象 ; alert(a); b = ; alert( ; [场景2]对象内部函数的this指向调用函数的当前对象 ; var bar = { a: , test ...
- 空间数据库系列一:geomesa&sparksql 分析环境搭建
geomesa sparksql 分析环境搭建 1.安装hbase-1.3.2.1 standlone版本,作为geomesa的store a.修改配置文件:hbase-1.3.2.1/conf/hb ...
- ssh日常优化使用
config文件的使用 ssh命令默认会加载 ~/.ssh/config 文件作为配置文件,如果没有则采用默认配置.如果我们想要对ssh进行定制,那么就可以使用如下方法 [root@linux-nod ...
- linux中的tasklet机制【转】
转自:http://blog.csdn.net/yasin_lee/article/details/12999099 转自: http://www.kerneltravel.net/?p=143 中断 ...
- (转)opencv 代替caffe.io.load_image
self.net.blobs[, , self.image_resize, self.image_resize) #image = caffe.io.load_image(image_file) im ...
- linux命令--head
head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 具体使用参考链接: h ...