圆方树第二题……

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

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

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

#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. vue入门——组件基础todolist

    1. 以下是 todolist 的例子,没有用到组件:下面的3 会通过组件拆分todolist <!DOCTYPE html> <html lang="en"&g ...

  2. vue 导出流文件excel

    第一种方法:需要设置响应类型,这里还需要安装 npm install js-file-download --save ,然后引用 var fileDownload = require('js-file ...

  3. HTML5+ MUI实现ajax的一个demo

    index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &l ...

  4. 10.1.5 Comment类型【JavaScript高级程序设计第三版】

    注释在DOM中是通过Comment 类型来表示的.Comment 节点具有下列特征: nodeType 的值为8: nodeName 的值为"#comment": nodeValu ...

  5. Yaf学习(二)----Yaf初体验

    1.hello world 1.1 用yaf输出hello world 1.首先配置host,nginx 2.host不用多说,指向虚拟机IP即可 1.2 重点说一下nginx (只说server块) ...

  6. Delphi初始化与结束化

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. ZooKeeper异常:Error connecting service It is probably not running

    ZooKeeper安装后使用以下命令可以启动成功 bin/zkServer.sh start 但是使用下面命令查看启动状态,则报错误: bin/zkServer.sh status Error con ...

  8. latex01-LaTeX环境的安装与配置

    以Tex Live (跨平台的发行版软件)为例. 1.官网下载iso镜像文件 2.用advanced.bat 安装(管理员权限) 选择要安装的包(主要是去掉多余的语言包) 测试Tex Live 是否正 ...

  9. 糖果 南阳acm589

    糖果 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 topcoder工作室的PIAOYIi超级爱吃糖果,现在他拥有一大堆不同种类的糖果,他准备一口气把它们吃完,可是 ...

  10. (数据科学学习手札24)逻辑回归分类器原理详解&Python与R实现

    一.简介 逻辑回归(Logistic Regression),与它的名字恰恰相反,它是一个分类器而非回归方法,在一些文献里它也被称为logit回归.最大熵分类器(MaxEnt).对数线性分类器等:我们 ...