[bzoj3306]树——树上倍增+dfs序+线段树
Brief Description
您需要写一种数据结构,支持:
- 更改一个点的点权
- 求一个子树的最小点权
- 换根
Algorithm Design
我们先忽略第三个要求。
看到要求子树的最小点权,我们想到使用dfs序。容易看到,一个节点的子树在dfs序中的范围就是\([l(x),r(x)]\),所以我们把树结构变成了线性结构,从而变成了一个RMQ问题,我们使用线段树即可求解。
对于换根,我们不必重新求出拓扑结构。我们考察换根会影响到的节点。对于新根的子树中的节点,一定没有影响,对于不是新根祖先的节点,一定也没有影响。所以我们只考虑新根的祖先。
我们可以看出,换成新根以后,祖先的覆盖范围就变成了全树抛去新根到祖先路径上距离祖先距离最近的节点的子树大小,设这个点为y,那么dfs序中的范围就是\([1,l[y]-1] \cup [r[y]+1, n]\)。
所以问题就变成了如何求树上离某个点距离最近的儿子。显然可以使用树上倍增来求。
Code
#include <algorithm>
#include <cstdio>
using std::max;
using std::min;
const int maxn = 100010;
int q[maxn], ind = 0, l[maxn], r[maxn], n, m, root, val[maxn], deep[maxn],
fa[maxn][20];
int cnt = 0;
struct edge {
int to, next;
} e[maxn];
int last[maxn];
struct seg {
int l, r, mn;
} t[maxn << 2];
void insert(int x, int y) {
e[++cnt].to = y;
e[cnt].next = last[x];
last[x] = cnt;
}
void update(int k) { t[k].mn = min(t[k << 1].mn, t[k << 1 | 1].mn); }
void dfs(int x) {
l[x] = ++ind;
q[ind] = x;
for (int i = 1; i <= 16; i++) {
if (deep[x] < (1 << i))
break;
fa[x][i] = fa[fa[x][i - 1]][i - 1];
}
for (int i = last[x]; i; i = e[i].next) {
fa[e[i].to][0] = x;
deep[e[i].to] = deep[x] + 1;
dfs(e[i].to);
}
r[x] = ind;
}
void build(int k, int l, int r) {
t[k].l = l, t[k].r = r;
int mid = (l + r) >> 1;
if (l == r) {
t[k].mn = val[q[l]];
return;
}
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
t[k].mn = min(t[k << 1].mn, t[k << 1 | 1].mn);
}
void modify(int k, int pos, int val) {
int l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (l == r) {
t[k].mn = val;
return;
}
if (pos <= mid)
modify(k << 1, pos, val);
else
modify(k << 1 | 1, pos, val);
update(k);
}
int query(int k, int x, int y) {
int l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (x <= l && r <= y)
return t[k].mn;
int ans = 0x3f3f3f;
if (x <= mid)
ans = min(ans, query(k << 1, x, y));
if (y > mid)
ans = min(ans, query(k << 1 | 1, x, y));
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
int f;
scanf("%d %d", &f, &val[i]);
if (f)
insert(f, i);
}
dfs(root = 1);
#ifndef ONLINE_JUDGE
for (int i = 1; i <= ind; i++)
printf("%d ", q[i]);
printf("\n");
#endif
build(1, 1, n);
while (m--) {
char ch[5];
int x;
scanf("%s %d", ch, &x);
if (ch[0] == 'V') {
int val;
scanf("%d", &val);
modify(1, l[x], val);
} else if (ch[0] == 'E')
root = x;
else {
if (root == x)
printf("%d\n", t[1].mn);
else if (l[x] <= l[root] && r[x] >= r[root]) { // x is the father of root
int y = root, d = deep[y] - deep[x] - 1;
for (int i = 0; i <= 16; i++)
if (d & (1 << i))
y = fa[y][i];
printf("%d\n", min(query(1, 1, l[y] - 1), query(1, r[y] + 1, n)));
} else
printf("%d\n", query(1, l[x], r[x]));
}
}
return 0;
}
[bzoj3306]树——树上倍增+dfs序+线段树的更多相关文章
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树
bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...
- BZOJ4034 [HAOI2015]树上操作+DFS序+线段树
参考:https://www.cnblogs.com/liyinggang/p/5965981.html 题意:是一个数据结构题,树上的,用dfs序,变成线性的: 思路:对于每一个节点x,记录其DFS ...
- BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】
一 题目 [HAOI2015]树上操作 二 分析 树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$. 1.和树链剖分一样,先用邻接链表建双向图. 2.跑两遍$dfs$,其实 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J. Ka Chang(树上分块+dfs序+线段树)
题意 链接:https://nanti.jisuanke.com/t/A1998 给出一个有根树(根是1),有n个结点.初始的时候每个结点的值都是0.下面有q个操作,操作有两种,操作1.将深度为L(根 ...
- Comet OJ - Contest #11 D isaster 重构树+倍增+dfs序+线段树
发现对于任意一条边,起决定性作用的是节点编号更大的点. 于是,对于每一条边,按照节点编号较大值作为边权,按照最小生成树的方式插入即可. 最后用线段树维护 dfs 序做一个区间查询即可. Code: # ...
- BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)
题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
随机推荐
- 《数据结构与算法分析:C语言描述》读书笔记
我们数据结构的课用了这本英文教材,作者是Mark Allen Weiss.总体来说比<算法导论>简单很多,但内容上交集非常大.其实是因为去掉了大多数证明和数学,对于没有耐心看符号和公式的人 ...
- Java之枚举笔记(Enum)
package com.simope.ljm; public class MyEnum { public static void main(String[] args) { System.out.pr ...
- 你可能会用到的"奇技赢巧"
工作中偶尔会遇到一些不常见的问题,但是解决起来又极其麻烦,通常要找很多资料才能搞定,这里我总结了近段时间遇到的一些问题,可能会对你有帮助,高手勿喷. 1.关于iPhone最下面会弹出奇怪框框的问题 就 ...
- 使用pyinstaller将Python打包为exe文件
当我们完成一个Python项目或一个程序时,希望将Python的py文件打包成在Windows系统下直接可以运行的exe程序,那么pyInstaller就是一个很好的选择.pyInstaller可以将 ...
- python终极篇 --- django---班级管理系统
周末没事自己写了个班级管理系统,虽然简单,但也算个前期学习的总结吧 from django.db import models # Create your models here. class Banj ...
- OpenPAI:大规模人工智能集群管理平台介绍及任务提交指南
产品渊源: 随着人工智能技术的快速发展,各种深度学习框架层出不穷,为了提高效率,更好地让人工智能快速落地,很多企业都很关注深度学习训练的平台化问题.例如,如何提升GPU等硬件资源的利用率?如何节省硬件 ...
- Halcon17对硬件配置要求
Halcon17对硬件配置要求 Halcon17已经发布出来了,很多朋友一定想安装这款机器视觉软件来学习,我们今天给大家讲解下,Halcon17对硬件配置的要求: Halcon17 For Wind ...
- 团队项目-第十次scrum 会议
时间:11.6 时长:20分钟 地点:主235教室走廊 工作情况 团队成员 已完成任务 待完成任务 解小锐 完成多种招聘方式的逻辑编写 陈鑫 实现游戏的存档功能 李金奇 添加多种招聘方式等功能 王辰昱 ...
- JavaSE复习(二)集合
Collection List(存取有序,有索引,可以重复) ArrayList 底层是数组实现的,线程不安全,查找和修改快,增和删比较慢 LinkedList 底层是链表实现的,线程不安全,增和删比 ...
- [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优(转)
最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...