比较基础的一道树链剖分的题 大概还是得说说思路
树链剖分是将树剖成很多条链,比较常见的剖法是按儿子的size来剖分,剖分完后对于这课树的询问用线段树维护——比如求路径和的话——随着他们各自的链向上走,直至他们在同一条链上为止。比较像lca的方法,只不过这里是按链为单位,而且隔壁的SymenYang说可以用树链剖分做lca。。吓哭
然后说说惨痛的调题经历:边表一定要开够啊! 不是n-1 而是2*(n-1)啊! 然后写变量时原始值和映射值要搞清楚啊! 不要搞错了! 还有就是下次求最小值一定看清下界是多少! 树的统计是-30000 ~ 30000 ,我果断naive 的写了一个初值为0!!! wa 0 就是这么痛苦! 还是too Young too Simple !
code :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = ; struct edge{
int t; edge* next;
}e[maxn*], *head[maxn];int ne = ; void addedge(int f, int t){
e[ne].t = t; e[ne].next = head[f]; head[f] = e + ne ++;
} int n;
int size[maxn],fa[maxn],dep[maxn],w[maxn],un[maxn],map[maxn]; struct node{
int smax, sum;
node *l, *r;
}tr[maxn * ], *root; int trne = ; node* build(int l, int r){
node* x = tr + trne ++;
if(l != r) {
int mid = (l + r) >> ;
x-> l = build(l, mid);
x-> r = build(mid + , r);
}
return x;
} void update(node* x){
if(x-> l) {
x-> sum = x-> l-> sum + x-> r->sum;
x-> smax = max(x-> l-> smax, x-> r-> smax);
}
} void insert(node* x, int l, int r, int pos, int v) {
if(l == r) { x-> sum = v, x-> smax = v;}
else{
int mid = (l + r) >> ;
if(pos <= mid) insert(x-> l, l, mid, pos, v);
else insert(x-> r, mid + , r, pos, v);
update(x);
}
} int ask(node* x, int l, int r, int ls, int rs, int flag) {
if(l == ls && r == rs) {
if(flag == ) return x-> smax;
else return x-> sum;
}
else {
int mid = (l + r) >> ;
if(rs <= mid) return ask(x-> l, l, mid, ls, rs, flag);
else if(ls >= mid + ) return ask(x-> r, mid + , r, ls, rs, flag);
else {
if(flag == )
return max(ask(x->l, l, mid, ls, mid, flag), ask(x-> r, mid + , r, mid + , rs, flag));
else
return ask(x-> l, l, mid, ls, mid, flag) + ask(x-> r, mid + , r, mid + , rs, flag);
}
}
} int cnt = ; void size_cal(int x, int pre) {
if(pre == -) dep[x] = , fa[x] = x;
else dep[x] = dep[pre] + , fa[x] = pre; size[x] = ;
for(edge* p = head[x]; p; p = p-> next)
if(dep[p-> t] == -)size_cal(p-> t, x), size[x] += size[p-> t];
} void divide(int x, int pre){
if(pre == -) un[x] = x;
else un[x] = un[pre];
map[x] = ++ cnt; insert(root, , n, map[x], w[x]);
int tmax = -, ts = -;
for(edge* p = head[x]; p; p = p-> next) {
if(dep[p-> t] > dep[x] && size[p-> t] > tmax) tmax = size[p-> t], ts = p-> t;
}
if(ts != -) {
divide(ts, x);
for(edge* p = head[x]; p; p = p-> next) {
if(dep[p-> t] > dep[x] && p-> t != ts) divide(p-> t, -);
}
}
} void read() {
memset(dep,-,sizeof(dep));
scanf("%d", &n);
root = build(, n);
for(int i = ; i <= n - ; i++) {
int f, t;
scanf("%d%d", &f, &t);
addedge(f, t), addedge(t, f);
}
for(int i = ; i <= n; ++ i) {
scanf("%d", &w[i]);
}
size_cal(, -);divide(, -);
} int sovmax(int a, int b) {
int ans = -; int ls, rs;
while(un[a] != un[b]) {
if(dep[un[a]] > dep[un[b]]) {
ls = map[a]; rs = map[un[a]];
if(ls > rs) swap(ls, rs);
ans = max(ans, ask(root, , n, ls, rs, ));
a = fa[un[a]];
}
else {
ls = map[b]; rs = map[un[b]];
if(ls > rs) swap(ls, rs);
ans = max(ans, ask(root, , n, ls, rs, ));
b = fa[un[b]];
}
}
ls = map[a], rs = map[b];
if(ls > rs) swap(ls,rs);
ans = max(ans, ask(root, , n, ls, rs, ));
return ans;
} int sovsum(int a,int b) {
int ans = ; int ls, rs;
while(un[a] != un[b]) {
if(dep[un[a]] > dep[un[b]]) {
ls = map[a], rs = map[un[a]];
if(ls > rs) swap(ls, rs);
ans += ask(root, , n, ls, rs, );
a = fa[un[a]];
}
else {
ls = map[b]; rs = map[un[b]];
if(ls > rs) swap(ls, rs);
ans += ask(root, , n, ls, rs, );
b = fa[un[b]];
}
}
ls = map[a], rs = map[b];
if(ls > rs) swap(ls, rs);
ans += ask(root, , n, ls, rs, );
return ans;
} void sov() {
int m;
scanf("%d", &m);
while(m --) {
char s[]; int ls, rs;
scanf("%s %d%d", s + , &ls, &rs);
if(s[] == 'M') printf("%d\n", sovmax(ls, rs));
if(s[] == 'S') printf("%d\n", sovsum(ls, rs));
if(s[] == 'H') insert(root, , n, map[ls], rs);
}
} int main(){
read();sov();
return ;
}
zjoi 2008 树的统计——树链剖分的更多相关文章
-
BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 23015 Solved: 9336[Submit ...
-
树的统计Count---树链剖分
NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...
-
BZOJ 1036 树的统计-树链剖分
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...
-
bzoj1036 树的统计 树链剖分模板
题意:给出树上任意两点,求路径上的值的和与最大值,带单点修改操作 树链剖分思路: 1.对树进行dfs求出点的深度和父亲节点,然后求出轻重儿子(重儿子就是点最多的那个子树,其余都是轻儿子),用一个son ...
-
BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)
潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...
-
BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
-
[ZJOI2008]树的统计——树链剖分
本题是一个树链剖分裸题,由于比较菜,老是RE,后来发现是因为使用了全局变量. /************************************************************ ...
-
[luogu P2590 ZJOI2008] 树的统计 (树链剖分)
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...
-
洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]
题目传送门 树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t ...
随机推荐
-
iOS开发masonry的一些使用简介
从一开始的纯代码计算frame,虽然自认为计算frame 刚刚的,但是到后来还是开始xib的自动约束和手动约束与frame搭配使用,经历这几种方式,大概一年前开始普遍使用masonry来代码约束之后也 ...
-
多校7 HDU5818 Joint Stacks
多校7 HDU5818 Joint Stacks 题意:n次操作.模拟栈的操作,合并的以后,每个栈里的元素以入栈顺序排列 思路:开三个栈,并且用到了merge函数 O(n)的复杂度 #include ...
-
Linux数据管理——文件锁定
一.什么是文件锁定 对于锁这个字,大家一定不会陌生,因为我们生活中就存在着大量的锁,它们各个方面发挥着它的作用,现在世界中的锁的功能都可归结为一句话,就是阻止某些人做某些事,例如,门锁就是阻止除了屋主 ...
-
【java设计模式】【创建模式Creational Pattern】单例模式Singleton Pattern
//饿汉式:资源利用率较低(无论是否需要都会创建),性能较高(使用前无需判断实例是否存在,可直接使用) public class EagerSingleton{ private static fina ...
-
sqlserver 2008R2新建数据库时报错,提示无法获得数据库";model";上的排它锁
刚新装了个sqlserver2008 R2,在建立数据库时候报错,提示无法获得数据库"model"上的排它锁.解决办法如下: 打开查询页面,执行下面的语句即可. use maste ...
-
LanProxy 内网映射穿透
前言:用过 ngrok 的人都知道,这是一个免费并且简便的内网映射工具,可是现在ngrok不知道弄啥?不能用了,那我们只能去找一些新的工具,下面是我跟我朋友一起弄的(主要是他教我(✪ω✪)),免费的, ...
-
html网页练习豆瓣网
html </head> <body> <!-- 头部 --> <header class="header1"> ...
-
【LeetCode每天一题】String to Integer (atoi)(字符串转换成数字)
Implement atoi which converts a string to an integer.The function first discards as many whitespace ...
-
linux内核中的cfq输入输出调度算法
1. 全称是什么? 完全公平调度算法(completely fair queuing) 2. 原理是怎样的? 先按照输入输出请求的地址进行排序,然后按排好的次序执行请求 3. 适用场景 适用于旋转式磁 ...
-
[性能调优]在PeopleSoft中使用函数索引
那些没有在PeopleSoft系统遇到性能问题的人,特别是基于Oracle数据库的PeopleSoft,可能不知道基于函数的索引. 根据定义,基于函数的索引是使用如下方法定义的: 基于表达式,例如算术 ...