【题解】【CF Round #278】Tourists
圆方树第二题……
图中询问的是指定两点之间简单路径上点的最小权值。若我们建出圆方树,圆点的权值为自身权值,方点的权值为所连接的圆点的权值最小值(即点双连通分量中的最小权值)。我们可以发现其实就是这两点在圆方树上经过的点的最小权值,因为在这上面若经过了一个方点,说明可以经过这个点双连通分量中任何一个点并且到达想到的点。(方点所连接的点都是相互可达的)。
所以问题转化为了求树上两点之间路径的最小点权。并且需要注意的是:链顶的点需要把它的父亲节点也考虑进来,因为它的父亲节点与它是属于同一个双连通分量的。感觉圆方树的好处在这里就可以体现出来:即可以通过一个点来反映出整个点双联通分量的情况,并且相连的方点圆点一定是父子关系,由此可以方便的在树上通过一条路径来总结出很多双联通分量的总情况。
所以:树剖+可修改堆可以完美解决。
#include <bits/stdc++.h>
using namespace std;
#define maxn 400000
#define int long long
#define INF 99999999999
int n, m, Q, val[maxn];
int tot, timer, dfn[maxn], low[maxn];
int cnt, fa[maxn], top[maxn], dep[maxn];
int S[maxn], size[maxn], hson[maxn]; struct node
{
int minn;
node () { minn = INF; }
}P[maxn]; struct heap
{
priority_queue <int, vector<int>, greater<int> > q1, q2;
void ins(int x) { q1.push(x); }
void erase(int x) { q2.push(x); }
int top()
{
while(!q2.empty() && q1.top() == q2.top()) q1.pop(), q2.pop();
return q1.top();
}
}Hp[maxn]; struct edge
{
int cnp = , head[maxn], to[maxn], last[maxn];
void add(int u, int v)
{
to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
}
}E1, E2; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void Tarjan(int u)
{
dfn[u] = low[u] = ++ timer; S[++ S[]] = u;
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(!dfn[v])
{
Tarjan(v); low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u])
{
E2.add(++ tot, u); int x = ;
do
{
x = S[S[] --]; E2.add(tot, x);
}while(x != v);
}
}
else low[u] = min(low[u], dfn[v]);
}
} void dfs(int u, int ff)
{
fa[u] = ff; dep[u] = dep[ff] + ; size[u] = ;
if(u <= n && ff) Hp[ff].ins(val[u]);
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i]; if(v == ff) continue;
dfs(v, u); size[u] += size[v];
if(size[v] > size[hson[u]]) hson[u] = v;
}
} void dfs2(int u, int gra)
{
dfn[u] = ++ timer; top[u] = gra;
if(hson[u]) dfs2(hson[u], gra);
for(int i = E2.head[u]; i; i = E2.last[i])
{
int v = E2.to[i];
if(v == fa[u] || v == hson[u]) continue;
dfs2(v, v);
}
} void update(int p, int l, int r, int x, int num)
{
if(l == r) { P[p].minn = num; return; }
int mid = (l + r) >> ;
if(x <= mid) update(p << , l, mid, x, num);
else update(p << | , mid + , r, x, num);
P[p].minn = min(P[p << ].minn, P[p << | ].minn);
} int query(int p, int l, int r, int L, int R)
{
if(l > R || r < L) return INF;
if(l >= L && r <= R) return P[p].minn;
int mid = (l + r) >> ;
return min(query(p << , l, mid, L, R), query(p << | , mid + , r, L, R));
} signed main()
{
tot = n = read(), m = read(), Q = read();
for(int i = ; i <= n; i ++) val[i] = read();
for(int i = ; i <= m; i ++)
{
int u = read(), v = read();
E1.add(u, v);
}
for(int i = ; i <= n; i ++)
if(!dfn[i]) Tarjan(i);
timer = ; dfs(, ), dfs2(, );
for(int i = ; i <= n; i ++) update(, , tot, dfn[i], val[i]);
for(int i = n + ; i <= tot; i ++) update(, , tot, dfn[i], Hp[i].top());
while(Q --)
{
char c; cin >> c; int a = read(), b = read();
if(c == 'C')
{
if(fa[a]) Hp[fa[a]].erase(val[a]);
val[a] = b; update(, , tot, dfn[a], val[a]);
if(fa[a]) Hp[fa[a]].ins(val[a]), update(, , tot, dfn[fa[a]], Hp[fa[a]].top());
}
else
{
int u = a, v = b, ans = INF;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ans = min(ans, query(, , tot, dfn[top[u]], dfn[u]));
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u, v);
ans = min(ans, query(, , tot, dfn[u], dfn[v]));
if(u > n) ans = min(ans, val[fa[u]]);
printf("%lld\n", ans);
}
}
return ;
}
【题解】【CF Round #278】Tourists的更多相关文章
- UOJ #30. [CF Round #278] Tourists
UOJ #30. [CF Round #278] Tourists 题目大意 : 有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种 ...
- 圆方树简介(UOJ30:CF Round #278 Tourists)
我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...
- [CF Round #278] Tourists
给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边. 蓝链 $ n,m,q \leq 100000, w_i \leq 10 ^7$ Solution 考虑建立用缩点双来建立广义圆 ...
- 竞赛题解 - CF Round #524 Div.2
CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...
- UOJ30——【CF Round #278】Tourists
1.感谢taorunz老师 2.题目大意:就是给个带权无向图,然后有两种操作, 1是修改某个点的权值 2是询问,询问一个值,就是u到v之间经过点权的最小值(不可以经过重复的点) 操作数,点数,边数都不 ...
- UOJ #30. 【CF Round #278】Tourists
Description Cyberland 有 n 座城市,编号从 1 到 n,有 m 条双向道路连接这些城市.第 j 条路连接城市 aj 和 bj.每天,都有成千上万的游客来到 Cyberland ...
- UOJ #30【CF Round #278】Tourists
求从$ x$走到$ y$的路径上可能经过的最小点权,带修改 UOJ #30 $ Solution:$ 如果两个点经过了某个连通分量,一定可以走到这个连通分量的最小值 直接构建圆方树,圆点存原点的点权 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- CF Round #580(div2)题解报告
CF Round #580(div2)题解报告 T1 T2 水题,不管 T3 构造题,证明大约感性理解一下 我们想既然存在解 \(|a[n + i] - a[i]| = 1\) 这是必须要满足的 既然 ...
随机推荐
- spring的事务处理
说到事务,无非就是事务的提交commit和回滚rollback. 事务是一个操作序列,这些操作要么全部都执行成功,事务去提交,要么就是有一个操作失败,事务去回滚. 要知道事务的4大特性ACID.即原子 ...
- 【cisco下针对冗余链路故障备份的处理措施】
对于中小型的网络中,为了流量的分担,可制定负载均衡方案,但往往带来的是链路的冗余.导致多条物理线路不能够最大的发挥其作用:冗余链路随可避免环路,但在实际的网络中还是存在一些需要完善的地方: 假设有一组 ...
- SHELL里执行HIVE导出文件处理成CSV文件
#!/bin/bash #用途: #.当前目录的txt文件批量转csv #.制表符转逗号分隔符 #.NULL去除 #.删除WARN警告 for i in `ls ./*.txt` do sed -e ...
- kafka概述
kafka概述 Apache Kafka是一个开源 消息 系统,由Scala写成.是由Apache软件基金会开发的一个开源消息系统项目. Kafka最初是由LinkedIn开发,并于2011年初开源. ...
- 通过SVI实现VLAN间通信
两个不同网段的计算机与三层交换机直连,通过SVI实现VLAN间通信vlan 1 //几个不同网段就创建几个VLANvlan 2 int f0/1 //划分VLANswitchport mode acc ...
- vue2.0 Axios 的简单用法
安装 使用 npm: $ npm install axios 使用 bower: $ bower install axios 使用 cdn: <script src="https:// ...
- PHP.42-TP框架商城应用实例-后台17-商品属性3-商品分类的修改与删除
商品分类的修改 1.改表单Goods/edit.html,加下拉框 2.因为商品属性修改涉及商品属性表goods_attr{id,attr_value,attr_id,goods_id}与属性表att ...
- 浅析express以及express中间件
一.express: 1.express: Express是什么? Express是基于node.js平台的web应用开发框架: 作用:可以实现快速搭建骨架: 优点:开发web应用更加方便,更加快捷. ...
- 还原T4模板执行前的警告对话框
T4模板在保存的时候都会弹出个对话框,确认是否立即执行,大部分情况下我是不想立即执行的,所以一般都点Cancel,只有想执行的时候才点OK. 今天操作的时候不小心勾选了“Do not show thi ...
- 云计算之路-阿里云上:Web服务器请求到达量突降
今天下午遇到了自使用阿里云以来首次遇到的新情况——http.sys的ArrivalRate突降(说明请求到达IIS的请求数量少了),而且SLB中的3台ECS都出现了这个问题. 1. 10.161.24 ...