圆方树简介(UOJ30:CF Round #278 Tourists)
我写这篇博客的原因
证明我也是学过圆方树的
顺便存存代码
前置技能
双联通分量:点双
然后就没辣
圆方树
建立
新建一个图
定义原图中的所有点为圆点
对于每个点双联通分量(只有两个点的也算)
建立一个方点,向所有的点双内的点连边
性质
- 一定是个森林
- 每个点双有唯一的方点
- 圆点方点相间分布,相同点不相邻
等等
例子 1
题面
求可以出现在两点之间的简单路路径上的点的最大权值,不带修改
分析
考虑用圆方树来解决
设圆点权值为本身,方点权值为点双中的最大权值
那么就是树上的路径最大权值
例子 2
还是上面的题,可以修改一个点的权值
类似题UOJ
用老方法
每次修改时更改圆点连接的所有方点
没了?
不存在的,这样每次修改是\(O(n)\)的,容易被卡
换一种定义:方点权值不包括它的父亲圆点
那么每次修改就只要修改圆点的父亲
注意如果\(lca\)是方点,还要算上它父亲方点的权值
堆+线段树(zkw辣)+树剖+圆方树+tarjan
UOJ代码
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(4e5 + 5);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
struct Edge{
int next[_], first[_], to[_], cnt;
IL void Init(){
Fill(first, -1);
}
IL void Add(RG int u, RG int v){
next[cnt] = first[u], to[cnt] = v, first[u] = cnt++;
}
} G1, G2;
struct Segment{
int mn[_ << 2], M;
IL void Init(RG int n){
Fill(mn, 127);
for(M = 1; M < n; M <<= 1);
}
IL void Update(RG int x, RG int y){
x += M - 1, mn[x] = y;
for(x >>= 1; x; x >>= 1) mn[x] = min(mn[x << 1], mn[x << 1 | 1]);
}
IL int Query(RG int l, RG int r){
RG int ret = 2e9;
for(l += M - 2, r += M; l ^ r ^ 1; l >>= 1, r >>= 1){
if(~l & 1) ret = min(ret, mn[l ^ 1]);
if(r & 1) ret = min(ret, mn[r ^ 1]);
}
return ret;
}
} T;
struct Heap{
priority_queue <int> Q1, Q2;
IL void Push(RG int x){
Q1.push(-x);
}
IL void Del(RG int x){
Q2.push(-x);
}
IL int Top(){
while(!Q2.empty() && Q1.top() == Q2.top()) Q1.pop(), Q2.pop();
return -Q1.top();
}
} Q[_];
int tmp, n, m, q, val[_], dfn[_], low[_], Index, S[_];
int size[_], top[_], fa[_], deep[_], son[_];
IL void Tarjan(RG int u){
dfn[u] = low[u] = ++Index, S[++S[0]] = u;
for(RG int e = G1.first[u]; e != -1; e = G1.next[e]){
RG int v = G1.to[e], x;
if(!dfn[v]){
Tarjan(v), low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]){
val[++n] = 2e9, x = 0;
do{
x = S[S[0]--];
G2.Add(n, x), G2.Add(x, n);
} while(x != v);
G2.Add(n, u), G2.Add(u, n);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
IL void Dfs1(RG int u){
size[u] = 1;
if(u <= tmp && fa[u]) Q[fa[u]].Push(val[u]);
for(RG int e = G2.first[u]; e != -1; e = G2.next[e]){
RG int v = G2.to[e];
if(size[v]) continue;
fa[v] = u, deep[v] = deep[u] + 1;
Dfs1(v);
size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
IL void Dfs2(RG int u, RG int Top){
dfn[u] = ++Index, top[u] = Top;
if(son[u]) Dfs2(son[u], Top);
for(RG int e = G2.first[u]; e != -1; e = G2.next[e])
if(!dfn[G2.to[e]]) Dfs2(G2.to[e], G2.to[e]);
}
IL int Query(RG int u, RG int v){
RG int ret = 2e9;
while(top[u] ^ top[v]){
if(deep[top[u]] > deep[top[v]]) swap(u, v);
ret = min(ret, T.Query(dfn[top[v]], dfn[v]));
v = fa[top[v]];
}
if(dfn[u] > dfn[v]) swap(u, v);
ret = min(ret, T.Query(dfn[u], dfn[v]));
if(u > tmp) ret = min(ret, val[fa[u]]);
return ret;
}
int main(RG int argc, RG char* argv[]){
G1.Init(), G2.Init();
tmp = n = Input(), m = Input(), q = Input();
for(RG int i = 1; i <= n; ++i) val[i] = Input();
for(RG int i = 1; i <= m; ++i){
RG int u = Input(), v = Input();
G1.Add(u, v), G1.Add(v, u);
}
for(RG int i = 1; i <= tmp; ++i) if(!dfn[i]) Tarjan(i);
Fill(dfn, 0), Index = 0, T.Init(n);
Dfs1(1), Dfs2(1, 1);
for(RG int i = 1; i <= n; ++i) T.Update(dfn[i], val[i]);
for(RG int i = tmp + 1; i <= n; ++i) T.Update(dfn[i], Q[i].Top());
for(RG int i = 1, a, b; i <= q; ++i){
RG char op; scanf(" %c", &op);
a = Input(), b = Input();
if(op == 'C'){
if(fa[a]) Q[fa[a]].Del(val[a]);
val[a] = b, T.Update(dfn[a], val[a]);
if(fa[a]) Q[fa[a]].Push(val[a]);
if(fa[a]) T.Update(dfn[fa[a]], Q[fa[a]].Top());
}
else printf("%d\n", Query(a, b));
}
return 0;
}
圆方树简介(UOJ30:CF Round #278 Tourists)的更多相关文章
- UOJ #30. [CF Round #278] Tourists
UOJ #30. [CF Round #278] Tourists 题目大意 : 有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种 ...
- 圆方树总结 [uoj30]Tourists
圆方树总结 所谓圆方树就是把一张图变成一棵树. 怎么变啊qaq 这里盗一张图 简单来说就是给每一个点双新建一个点,然后连向这个点双中的每一个点.特殊的,把两个点互相连通的也视作一个点双. 我们把原来就 ...
- [CF Round #278] Tourists
给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边. 蓝链 $ n,m,q \leq 100000, w_i \leq 10 ^7$ Solution 考虑建立用缩点双来建立广义圆 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- 仙人掌 && 圆方树 && 虚树 总结
仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...
- BZOJ5329:[SDOI2018]战略游戏(圆方树,虚树)
Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...
- 仙人掌&圆方树
仙人掌&圆方树 Tags:图论 [x] [luogu4320]道路相遇 https://www.luogu.org/problemnew/show/P4320 [ ] [SDOI2018]战略 ...
- UOJ.87.mx的仙人掌(圆方树 虚树)(未AC)
题目链接 本代码10分(感觉速度还行..). 建圆方树,预处理一些东西.对询问建虚树. 对于虚树上的圆点直接做:对于方点特判,枚举其所有儿子,如果子节点不在该方点代表的环中,跳到那个点并更新其val, ...
随机推荐
- [CQOI2006]凸多边形
很明显是一道半平面交的题. 先说一下半平面交的步骤: 1.用点向法(点+向量)表示直线 2.极角排序,若极角相同,按相对位置排序. 3.去重,极角相同的保留更优的 4.枚举边维护双端队列 5.求答案 ...
- OpenCV角点检测goodFeaturesToTrack()源代码分析
上面一篇博客分析了HARRIS和ShiTomasi角点检测的源代码.而为了提取更准确的角点,OpenCV中提供了goodFeaturesToTrack()这个API函数,来获取更加准确的角点位置.这篇 ...
- 洛谷P1896 [SCOI2005]互不侵犯King【状压DP】
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入格式: 只有一行,包含两个数N,K ...
- 谷歌内核浏览器 iframe内容的 tab切换 滚动条消失
问题: 新版本的-webkit- 内核浏览器 在tab切换时,iframe 内容区 丢失滚动条 如下图 (虽然滚动条位置还在,可以垂直滚动,但滚动条不见了) 解决思路: 让iframe重新计算宽高,重 ...
- 【学习笔记】Hibernate HQL连接查询和数据批处理 (Y2-1-7)
HQL连接查询 和SQL查询一样 hql也支持各种链接查询 如内连接 外连接 具体如下 左外连接 left (outer) join 迫切左外连接 left (outer) join fetch 右外 ...
- JavaScript面向对象学习笔记
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)--每个对象拥有一个原型对象,对象以其原型为模板.从原型继承方法和属性.原型对象也可能拥有原型, ...
- python实现三级菜单
一.要求: 1.一开始打印出所有省份和提示 2.用户输入省份以此查询城市 3.在按照输出的城市名提示用户输入,最后输出用户所查询的区县名 4.随时输入"back"可以返回上一级菜单 ...
- 使用Netbeans内置的Git工具
在 NetBeans IDE 中使用 Git 支持 NetBeans IDE 为 Git 版本控制客户端提供支持.通过利用 IDE 的 Git 支持,您可以从 IDE 内的项目中直接执行版本控制任务. ...
- 中小研发团队架构实践之微服务MSA
一.MSA简介 1.1.MSA是什么 微服务架构MSA是Microservice Architecture的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯.互相配合, ...
- Kaggle新手入门之路
学完了Coursera上Andrew Ng的Machine Learning后,迫不及待地想去参加一场Kaggle的比赛,却发现从理论到实践的转变实在是太困难了,在此记录学习过程. 一:安装Anaco ...