bzoj3306: 树(dfs序+倍增+线段树)
比较傻逼的一道题...
显然求子树最小值就是求出dfs序用线段树维护嘛
换根的时候树的形态不会改变,所以我们可以根据相对于根的位置分类讨论。
如果询问的x是根就直接输出整棵树的最小值。
如果询问的x是根在原树上的子节点,直接输出子树的最小值。
如果询问的x是根在原树上的祖先,那么就要输出整棵树去掉x在原树上那个包含根的子节点的子树的答案。
至于怎么求x在原树上那个包含根的子节点,可以用倍增。
但是我发现直接遍历x的子节点居然不会被卡,而且还跑到了第一页嘿嘿嘿
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
const int maxn=, inf=1e9;
struct poi{int too, pre;}e[maxn];
struct tjm{int sum;}tree[maxn<<];
int n, q, x, y, tot, tott, root;
int a[maxn], last[maxn], l[maxn], r[maxn], pos[maxn], d[maxn], f[maxn][];
char s[];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y){e[++tot].too=y; e[tot].pre=last[x]; last[x]=tot;}
void dfs(int x)
{
l[x]=++tott; pos[tott]=x; d[x]=d[f[x][]]+;
for(int i=last[x];i;i=e[i].pre) f[e[i].too][]=x, dfs(e[i].too);
r[x]=tott;
}
inline int min(int a, int b) {return a<b?a:b;}
inline void up(int x) {tree[x].sum=min(tree[x<<].sum, tree[x<<|].sum);}
void build(int x, int l, int r)
{
if(l==r) {tree[x].sum=pos[l]?a[pos[l]]:inf; return;}
int mid=(l+r)>>;
build(x<<, l, mid); build(x<<|, mid+, r);
up(x);
}
void update(int x, int l, int r, int cx, int delta)
{
if(l==r) {tree[x].sum=delta; return;}
int mid=(l+r)>>;
if(cx<=mid) update(x<<, l, mid, cx, delta);
else update(x<<|, mid+, r, cx, delta);
up(x);
}
int query(int x, int l, int r, int cl, int cr)
{
if(cl>cr) return inf;
if(cl<=l && r<=cr) return tree[x].sum;
int mid=(l+r)>>, ans=inf;
if(cl<=mid) ans=query(x<<, l, mid, cl, cr);
if(cr>mid) ans=min(ans, query(x<<|, mid+, r, cl, cr));
return ans;
}
inline int solve(int x)
{
if(x==root) return tree[].sum;
if(l[x]>l[root] || r[x]<l[root]) return query(, , n, l[x], r[x]);
int now=root;
for(int i=;i>=;i--) if(d[f[now][i]]>x) now=f[now][i];
return min(query(, , n, , l[now]-), query(, , n, r[now]+, n));
}
int main()
{
read(n); read(q);
for(int i=;i<=n;i++)
{
read(x); read(a[i]);
if(x) add(x, i);
}
dfs(root=); build(, , n);
for(int j=;j<=;j++) for(int i=;i<=n;i++) f[i][j]=f[f[i][j-]][j-];
for(int i=;i<=q;i++)
{
scanf("%s", s+);
if(s[]=='V') read(x), read(y), update(, , n, l[x], y);
else if(s[]=='E') read(root);
else read(x), printf("%d\n", solve(x));
}
}
bzoj3306: 树(dfs序+倍增+线段树)的更多相关文章
- Codeforces 877E - Danil and a Part-time Job(dfs序+线段树)
877E - Danil and a Part-time Job 思路:dfs序+线段树 dfs序:http://blog.csdn.net/qq_24489717/article/details/5 ...
- [bzoj3306]树_dfs序_线段树_倍增lca
树 bzoj-3306 题目大意:给定一颗n个节点的树,支持换根.修改点权.查询子树最小值. 注释:$1\le n,q\le 10^5$. 想法: 如果没有换根操作,就是$dfs$序+线段树维护区间最 ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- bzoj2819 DFS序 + LCA + 线段树
https://www.lydsy.com/JudgeOnline/problem.php?id=2819 题意:树上单点修改及区间异或和查询. 思维难度不高,但是题比较硬核. 整体思路是维护每一个结 ...
- 用dfs序处理线段树的好题吗?
https://www.cnblogs.com/mountaink/p/9878918.html 分析:每次的选取必须选最优的一条链,那我们考虑一下选择这条链后,把这条路上的点的权值更新掉,再采取选最 ...
- 7月13日考试 题解(DFS序+期望+线段树优化建图)
T1 sign 题目大意:给出一棵 N 个节点的树,求所有起点为叶节点的有向路径,其 上每一条边权值和的和.N<=10000 水题.考试的时候毒瘤出题人(学长orz)把读入顺序改了一下,于是很多 ...
- hdu 3974 Assign the task(dfs序上线段树)
Problem Description There is a company that has N employees(numbered from 1 to N),every employee in ...
- Luogu P2982 [USACO10FEB]慢下来 Slowing down | dfs序、线段树
题目链接 题目大意: 有一棵N个结点树和N头奶牛,一开始所有奶牛都在一号结点,奶牛们将按从编号1到编号N的顺序依次前往自己的目的地,求每头奶牛在去往自己目的地的途中将会经过多少已经有奶牛的结点. 题解 ...
- Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)
思路: dfs序其实是很水的东西. 和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的 ...
随机推荐
- 抓包工具Charles学习总结
最近由于工作需要对App进行测试,功能方面还好说,但是在网络测试方面遇到了一些问题.由于公司App是使用https进行通信,直接在路由器上抓包下来,数据包都是加密的,没法看到接口返回的内容,给测试的B ...
- CentOS 6.8 安装JDK8
JDK安装 1.查看环境是否有默认jdk,输入命令: rpm -qa | grep jdk 如果有默认jdk,可以使用 yum remove 删除 2.进入系统根目录,创建developer文件夹 3 ...
- ES6 之 解构赋值
本博文配合 阮一峰 <ES6 标准入门(第3版)>一书进行简要概述 ES6 中变量的解构赋值. 数组的解构赋值 基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这 ...
- Linux内核学习笔记(3)-- 进程的创建和终结
一. 进程创建: Unix 下的进程创建很特别,与许多其他操作系统不同,它分两步操作来创建和执行进程: fork() 和 exec() .首先,fork() 通过拷贝当前进程创建一个子进程:然后,ex ...
- ASCII码中的可见字符
ASCII码中 包括空格的可见字符从32到126共95个 不包括则为94
- VIM字符编码基础知识
1 字符编码基础知识 字符编码是计算机技术中最基本和最重要的知识之一.如果缺乏相关知识,请自行恶补之.这里仅做最简要的说明. 1.1 字符编码概述 所谓的字符编码,就是对人类发明的每一个文字进行数字 ...
- “我爱淘”第二冲刺阶段Scrum站立会议7
完成任务: 完成学院分类的点击查看书籍功能,可以点击书的条目查看书的详细信息.将登陆界面以及注册发布界面完善了一下修复一些bug. 计划任务: 将书的详细信息进行完善,并且可以点击收藏以及已预订等功能 ...
- Nginx 使用札记
nginx是什么? nginx是俄罗斯人 Igor Sysoev为俄罗斯访问量第二的Rambler.ru站点开发的一个十分轻量级的HTTP服务器.它是一个高性能的HTTP和反向代理服务器,同时也可以作 ...
- 电梯V2.0
电梯V2.0 GitHub仓库地址 Problem 一栋10层的大楼(楼层编号1-10),设3台无限载重的电梯,初始时电梯停在1层.其中:1号电梯只能停留在奇数层,2号电梯可以各层都停留,3号电梯只停 ...
- (工具类)MD5算法|时间格式转换|字符串转数字
package vote.utils; import java.security.MessageDigest; import java.text.SimpleDateFormat; import ja ...