圆方树第二题……

  图中询问的是指定两点之间简单路径上点的最小权值。若我们建出圆方树,圆点的权值为自身权值,方点的权值为所连接的圆点的权值最小值(即点双连通分量中的最小权值)。我们可以发现其实就是这两点在圆方树上经过的点的最小权值,因为在这上面若经过了一个方点,说明可以经过这个点双连通分量中任何一个点并且到达想到的点。(方点所连接的点都是相互可达的)。

  所以问题转化为了求树上两点之间路径的最小点权。并且需要注意的是:链顶的点需要把它的父亲节点也考虑进来,因为它的父亲节点与它是属于同一个双连通分量的。感觉圆方树的好处在这里就可以体现出来:即可以通过一个点来反映出整个点双联通分量的情况,并且相连的方点圆点一定是父子关系,由此可以方便的在树上通过一条路径来总结出很多双联通分量的总情况。

  所以:树剖+可修改堆可以完美解决。

#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的更多相关文章

  1. UOJ #30. [CF Round #278] Tourists

    UOJ #30. [CF Round #278] Tourists 题目大意 : 有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种 ...

  2. 圆方树简介(UOJ30:CF Round #278 Tourists)

    我写这篇博客的原因 证明我也是学过圆方树的 顺便存存代码 前置技能 双联通分量:点双 然后就没辣 圆方树 建立 新建一个图 定义原图中的所有点为圆点 对于每个点双联通分量(只有两个点的也算) 建立一个 ...

  3. [CF Round #278] Tourists

    给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边. 蓝链 $ n,m,q \leq 100000, w_i \leq 10 ^7$ Solution 考虑建立用缩点双来建立广义圆 ...

  4. 竞赛题解 - CF Round #524 Div.2

    CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...

  5. UOJ30——【CF Round #278】Tourists

    1.感谢taorunz老师 2.题目大意:就是给个带权无向图,然后有两种操作, 1是修改某个点的权值 2是询问,询问一个值,就是u到v之间经过点权的最小值(不可以经过重复的点) 操作数,点数,边数都不 ...

  6. UOJ #30. 【CF Round #278】Tourists

    Description Cyberland 有 n 座城市,编号从 1 到 n,有 m 条双向道路连接这些城市.第 j 条路连接城市 aj 和 bj.每天,都有成千上万的游客来到 Cyberland ...

  7. UOJ #30【CF Round #278】Tourists

    求从$ x$走到$ y$的路径上可能经过的最小点权,带修改  UOJ #30 $ Solution:$ 如果两个点经过了某个连通分量,一定可以走到这个连通分量的最小值 直接构建圆方树,圆点存原点的点权 ...

  8. uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)

    - 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...

  9. CF Round #580(div2)题解报告

    CF Round #580(div2)题解报告 T1 T2 水题,不管 T3 构造题,证明大约感性理解一下 我们想既然存在解 \(|a[n + i] - a[i]| = 1\) 这是必须要满足的 既然 ...

随机推荐

  1. javascript--BOM的onload事件和onunload事件

    1.onload事件 onload,页面加载后执行,所谓页面加载完成,指页面上所有的元素创建完毕,引用的所有的外部资源(js.css.图片)等下载完毕. 所以onload执行的比较晚,因为如果页面上有 ...

  2. ASP.NET成员资格和角色管理

    一.成员资格管理 1.成员资格管理模型 ASP.NET提供的成员资格管理功能,其核心是利用内置的成员库表(SQL Server).成员资格管理API(Membership.MembershipUser ...

  3. PHP判断URL地址百度是否已经收录并主动提交MIP数据

    /** * PHP检测URL地址百度是否已经收录 * @param string $url 要检测的URL地址 */ function Baidu($url) { $url = 'http://www ...

  4. MR执行流程

    1.Map任务处理 1.1 读取HDFS中的文件.每一行解析成一个<k,v>.每一个键值对调用一次map函数. <0,hello you>   <10,hello me& ...

  5. Python学习之魔法方法

    Python中会看到前后都加双下划线的函数名,例如 __init__(self),这类写法在Python中具有特殊的含义.如果对象使用了这类方法中的某一个,那么这个方法将会在特殊的情况下被执行,然而几 ...

  6. Node.js中的不安全跳转如何防御详解

    Node.js中的不安全跳转如何防御详解 导语: 早年在浏览器大战期间,有远见的Chrome认为要运行现代Web应用,浏览器必须有一个性能非常强劲的Java引擎,于是Google自己开发了一个高性能的 ...

  7. json模块、os模块

    一.eval模拟序列化操作 1.序列化 内存中的数据-------->转成一种中间格式(字符串)---------->存到文件中 dic={'name':'egon','age':18} ...

  8. (数据科学学习手札14)Mean-Shift聚类法简单介绍及Python实现

    不管之前介绍的K-means还是K-medoids聚类,都得事先确定聚类簇的个数,而且肘部法则也并不是万能的,总会遇到难以抉择的情况,而本篇将要介绍的Mean-Shift聚类法就可以自动确定k的个数, ...

  9. R语言学习笔记(十):零碎知识点(21-25)

    21--assign() assign函数可以通过变量名的字符串来赋值 > assign('a', 1:3) > a [1] 1 2 3 > b <- c('a') > ...

  10. Android stadio bug

    好生气啊,android stadio 有bug.自己的代码,一直没有生效,原来是stadio 的问题.只是因为我打开了增强模式,后来,buildToolVersion 改了之后,android st ...