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的 ...
随机推荐
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) E. The Supersonic Rocket
这道题比赛之后被重新加了几个case,很多人现在都过不了了 算法就是先求凸包,然后判断两个凸包相等 我们可以吧凸包序列化为两点距离和角度 角度如果直接拿向量的叉积是不对的,,因为钝角和锐角的叉积有可能 ...
- Qt creator 最常用的13个快捷键
alt +enter // 自动创建类的定义 F1 // 查看帮助,文档 F2 // 快速到变量声明 Shift + F2 // 函数的声明和定义之间快速切换 F4 // 在 cpp 和 h 文件切换 ...
- NUMA 体系架构
NUMA 体系架构 SMP 体系架构 NUMA 体系架构 NUMA 结构基本概念 Openstack flavor NUMA 策略 Nova 实现 NUMA 流程 1. SMP 体系架构 CPU 计算 ...
- PayPal接洽苹果 欲承接手机支付外包
不久前,<华尔街日报>等媒体报道,苹果正计划利用iTunes内部支付功能,推出第三方手机支付服务.美国科技 新闻网站Recode1月30日引述消息人士称,移动支付领军厂商PayPal,目前 ...
- arcgis10.2怎么把地理坐标系转化为投影坐标系(平面,米制坐标) arcmap 10.2 从 WGS_1984 转 Beijing_1954
方法一:在Arcmap中转换:从 WGS_1984 转 Beijing_19541.加载要转换的数据,右下角为经纬度2.点击视图——数据框属性——坐标系统3.导入或选择正确的坐标系(如选:Beijin ...
- CF刷刷水题找自信1
CF 1108A Two distinct points 题目意思:给你两个线段的起点和终点,让你给出两个不同的点,这两点分别处于两个不同的线段之中.解题思路:题目说如果存在多种可能的点,随意一组答案 ...
- Thunder团队第七周 - Scrum会议2
Scrum会议2 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 参会成员: 王航(Master):http://www.cnblogs.com/wangh ...
- HDU 5211 Mutiple 水题
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5211 题解: 1.筛法: #include<iostream> #include< ...
- python处理时间相关的方法(汇总)
记录python处理时间的模块:time模块.datetime模块和calendar模块. python版本:2.7 在介绍模块之前,先说下以下几点: 1.时间通常有这几种表示方式: a.时间戳:通常 ...
- lintcode-418-整数转罗马数字
418-整数转罗马数字 给定一个整数,将其转换成罗马数字. 返回的结果要求在1-3999的范围内. 说明 什么是 罗马数字? https://en.wikipedia.org/wiki/Roman_n ...