[JLOI2014]松鼠的新家 (树剖)
题目
解析
非常裸的一道树剖题
链上修改+单点查询的板子
记录一下所经过的点\(now[i]\),每次更新\(now[i-1]到now[i]\)
我们链上更新时上一次到的终点,是这一次一次更新的起点,又因为在\(a_n\)处可以不放糖,所以我们每次链上更新完成后,在上条链的终点位置处糖数\(-1\)。
然后套板子直接做
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, m, num, cnt;
int head[N], size[N], f[N], top[N], son[N], dep[N], now[N], id[N];
class node {
public :
int v, nx;
} e[N];
class tree {
public :
int sum, lazy;
int len;
} t[N];
#define lson rt << 1
#define rson rt << 1 | 1
template<class T>inline void read(T &x) {
x = 0; int f = 0; char ch = getchar();
while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x = f ? -x : x;
return ;
}
inline void add(int u, int v) {
e[++num].nx = head[u], e[num].v = v, head[u] = num;
}
void dfs1(int u, int fa) {
size[u] = 1;
for (int i = head[u]; ~i; i = e[i].nx) {
int v = e[i].v;
if (v != fa) {
dep[v] = dep[u] + 1;
f[v] = u;
dfs1(v, u);
size[u] += size[v];
if (size[v] > size[son[u]]) son[u] = v;
}
}
}
void dfs2(int u, int t) {
id[u] = ++cnt;
top[u] = t;
if (son[u]) dfs2(son[u], t);
for (int i = head[u]; ~i; i = e[i].nx) {
int v = e[i].v;
if (v != f[u] && v != son[u]) dfs2(v, v); //WRONG
}
}
inline void pushup(int rt) {
t[rt].sum = t[lson].sum + t[rson].sum;
}
void build(int l, int r, int rt) {
t[rt].len = r - l + 1;
if (l == r) return;
int m = (l + r) >> 1;
build(l, m, lson);
build(m + 1, r, rson);
}
inline void pushdown(int rt) {
if (t[rt].lazy) {
t[lson].lazy += t[rt].lazy;
t[rson].lazy += t[rt].lazy;
t[lson].sum += t[rt].lazy * t[lson].len;
t[rson].sum += t[rt].lazy * t[rson].len;
t[rt].lazy = 0;
}
}
void update(int L, int R, int c, int l, int r, int rt) {
if (L <= l && r <= R) {
t[rt].sum += (t[rt].len * c);
t[rt].lazy += c;
return;
}
pushdown(rt);
int m = (l + r) >> 1;
if (L <= m) update(L, R, c, l, m, lson);
if (R > m) update(L, R, c, m + 1, r, rson);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return t[rt].sum;
pushdown(rt);
int m = (l + r) >> 1, ans = 0;
if (L <= m) ans += query(L, R, l, m, lson);
if (R > m) ans += query(L, R, m + 1, r, rson);
return ans;
}
void update_chain(int x, int y, int z) {
int fx = top[x], fy = top[y];
while (fx != fy) {
if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
update(id[fx], id[x], z, 1, cnt, 1);
x = f[fx], fx = top[x];
}
if (id[x] > id[y]) swap(x, y);
update(id[x], id[y], z, 1, cnt, 1);
}
int main() {
memset(head, -1, sizeof(head));
read(n);
for (int i = 1, x; i <= n; ++i) read(x), now[i] = x;
for (int i = 1, x, y; i < n; ++i) read(x), read(y), add(x, y), add(y, x);
f[1] = 0, dep[1] = 0;
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
for (int i = 2; i <= n; ++i) update_chain(now[i - 1], now[i], 1), update_chain(now[i], now[i], -1);
for (int i = 1; i <= n; ++i) printf("%d\n", query(id[i], id[i], 1, n, 1));
return 0;
}
[JLOI2014]松鼠的新家 (树剖)的更多相关文章
- Bzoj 3631: [JLOI2014]松鼠的新家(树链剖分+线段树)
3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MB Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...
- BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )
裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...
- P3258 [JLOI2014]松鼠的新家 树链剖分
这个题就是一道树剖板子题,就是每走一步就把所有的经过点加一就行了.还有,我的树剖板子没问题!!!谁知道为什么板子T3个点!我不管了!反正这道题正常写A了. 题干: 题目描述 松鼠的新家是一棵树,前几天 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)
题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...
- [JLOI2014]松鼠的新家-树链剖分
最开始的时候我在写线段树部分的时候还打了一个build,后来一想,打个球球大作战的build啊!!!有个锤子的用啊!!! #include<bits/stdc++.h> using nam ...
- 树链剖分 [JLOI2014]松鼠的新家
[JLOI2014]松鼠的新家 时间限制: 1 Sec 内存限制: 128 MB 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达, ...
- [JLOI2014]松鼠的新家(树链剖分)
[JLOI2014]松鼠的新家(luogu) Description 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间 ...
- [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)
今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...
随机推荐
- Spring Cloud Ribbon 源码分析---负载均衡算法
上一篇分析了Ribbon如何发送出去一个自带负载均衡效果的HTTP请求,本节就重点分析各个算法都是如何实现. 负载均衡整体是从IRule进去的: public interface IRule{ /* ...
- git 执行 git reset HEAD 报 Unstaged changes after reset
Unstaged changes after reset 解决的办法如下2中办法: 1. git add . git reset --hard 2. git stash git stash dro ...
- 【Node.js】Node.js的调试
目录结构: contents structure [-] 使用console.log() 使用Chrome DevTools 使用Visual Studio Code 与JavaScript运行在浏览 ...
- shell 备份mysql
shell脚本备份mysql,放在crontab中,可以作为每日测试用数据库备份 #!/bin/bash string_time=`date +%Y%m%d%H%M`; file_path=`date ...
- Spring源码解析之PropertyPlaceholderHelper(占位符解析器)
Spring源码解析之PropertyPlaceholderHelper(占位符解析器) https://blog.csdn.net/weixin_39471249/article/details/7 ...
- LeetCode 108. Convert Sorted Array to Binary Search Tree (将有序数组转换成BST)
108. Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascendin ...
- Linux实现定时备份MySQL数据库并删除30天前的备份文件
1. MySQL5.6以上版本 2. 修改 /etc/my.cnf 文件 # vim /etc/my.cnf [client] host=localhost user=你的数据库用户 password ...
- 浏览器查看和手动设置cookie的值
1.查看:按F12进入浏览器的开发者模式——console——在命令行输入javascript:alert(document.cookie),再回车 2.按F12进入浏览器的开发者模式——consol ...
- Python线程池及其原理和使用(超级详细)
系统启动一个新线程的成本是比较高的,因为它涉及与操作系统的交互.在这种情形下,使用线程池可以很好地提升性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 线程池在系统启动时即 ...
- Android组件化aar躺坑记:ButterKnife 报 元素值必须为常量表达式错误
背景: 项目有需求,将自己写的模块作为一个module给到大项目使用,所以准备把自己的项目打包成aar包. 一.如何将独立项目打包成aar: 1.修改module下的application 为libr ...