CF487E Tourists--圆方树
既然有这条性质,这题就很简单了:
\(可能在a->b的简单路径上的点集,就是圆方树上a->b路径上方点代表的点双的并集\)
对每一个方点维护一个\(multiset\),代表其在圆方树上子结点的最小值,这样更改就只需要改父结点辣。剩下的用树剖乱搞就行了
#include <bits/stdc++.h>
using namespace std;
#define N 200000
#define INF 0x3f3f3f3f
#define lson (o<<1)
#define rson (o<<1|1)
#define mid ((l+r)>>1)
int n, m, q, tot;
int w[N+5], dfn_clk, dfn[N+5], low[N+5], id[N+5];
int stk[N+5], tp;
int sz[N+5], fa[N+5], hson[N+5], rt[N+5], top[N+5], d[N+5];
vector<int> G[N+5], T[N+5];
int minv[4*N+5];
multiset<int> s[N+5];
void tarjan(int u) {
low[u] = dfn[u] = ++dfn_clk;
stk[++tp] = u;
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
if(low[v] == dfn[u]) {
++tot;
for(int x = 0; x != v; --tp) {
x = stk[tp];
T[tot].push_back(x);
T[x].push_back(tot);
}
T[tot].push_back(u);
T[u].push_back(tot);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
int minval(int u) {
if(s[u].size()) return *s[u].begin();
else return INF;
}
void dfs1(int u, int pa) {
fa[u] = pa;
sz[u] = 1;
d[u] = d[pa]+1;
for(int i = 0; i < T[u].size(); ++i) {
int v = T[u][i];
if(v == pa) continue;
if(u > n) s[u].insert(w[v]);
dfs1(v, u);
if(sz[v] > sz[hson[u]]) hson[u] = v;
sz[u] += sz[v];
}
}
void dfs2(int u, int tp) {
dfn[u] = ++dfn_clk, id[dfn_clk] = u;
top[u] = tp;
if(hson[u]) dfs2(hson[u], tp);
for(int i = 0; i < T[u].size(); ++i) {
int v = T[u][i];
if(v == fa[u] || v == hson[u]) continue;
dfs2(v, v);
}
rt[u] = dfn_clk;
}
int lca(int x, int y) {
while(top[x] != top[y]) d[top[x]] > d[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
return d[x] < d[y] ? x : y;
}
void pushup(int o) {
minv[o] = min(minv[lson], minv[rson]);
}
void build(int o, int l, int r) {
if(l == r) {
minv[o] = id[l] > n ? minval(id[l]) : INF;
return ;
}
build(lson, l, mid), build(rson, mid+1, r);
pushup(o);
}
void modify(int o, int l, int r, int x, int k) {
if(l == r) {
minv[o] = k;
return ;
}
if(x <= mid) modify(lson, l, mid, x, k);
else modify(rson, mid+1, r, x, k);
pushup(o);
}
int queryMin(int o, int l, int r, int L, int R) {
if(L <= l && r <= R) return minv[o];
int ret = INF;
if(L <= mid) ret = min(ret, queryMin(lson, l, mid, L, R));
if(R > mid) ret = min(ret, queryMin(rson, mid+1, r, L, R));
return ret;
}
int query(int x, int y) {
int z = lca(x, y), ret = INF;
while(top[x] != top[z]) ret = min(ret, queryMin(1, 1, tot, dfn[top[x]], dfn[x])), x = fa[top[x]];
ret = min(ret, queryMin(1, 1, tot, dfn[z], dfn[x]));
while(top[y] != top[z]) ret = min(ret, queryMin(1, 1, tot, dfn[top[y]], dfn[y])), y = fa[top[y]];
ret = min(ret, queryMin(1, 1, tot, dfn[z], dfn[y]));
if(z > n) ret = min(ret, w[fa[z]]);
else ret = min(ret, w[z]);
return ret;
}
int main() {
scanf("%d%d%d", &n, &m, &q);
tot = n;
for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);
for(int i = 1, x, y; i <= m; ++i) {
scanf("%d%d", &x, &y);
G[x].push_back(y), G[y].push_back(x);
}
tarjan(1);
dfn_clk = 0;
dfs1(1, 0), dfs2(1, 1);
build(1, 1, tot);
char type[2];
for(int i = 1, x, y; i <= q; ++i) {
scanf("%s%d%d", type, &x, &y);
if(type[0] == 'C') {
if(x != 1) {
int t = minval(fa[x]);
s[fa[x]].erase(s[fa[x]].lower_bound(w[x]));
s[fa[x]].insert(y);
if(minval(fa[x]) != t) modify(1, 1, tot, dfn[fa[x]], minval(fa[x]));
}
w[x] = y;
}
else {
printf("%d\n", query(x, y));
}
}
return 0;
}
CF487E Tourists--圆方树的更多相关文章
- CF487E Tourists(圆方树+树链剖分+multiset/可删堆)
CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...
- CF487E Tourists 圆方树、树链剖分
传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...
- CF487E Tourists[圆方树+树剖(线段树套set)]
做这题的时候有点怂..基本已经想到正解了..结果感觉做法有点假,还是看了正解题解.. 首先提到简单路径上经过的点,就想到了一个关于点双的结论:两点间简单路径上所有可能经过的点的并等于路径上所有点所在点 ...
- CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...
- Tourists——圆方树
CF487E Tourists 一般图,带修求所有简单路径代价. 简单路径,不能经过同一个点两次,那么每个V-DCC出去就不能再回来了. 所以可以圆方树,然后方点维护一下V-DCC内的最小值. 那么, ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- CF487E Tourists 【圆方树 + 树剖 + 堆】
题目链接 CF487E 题解 圆方树 + 树剖 裸题 建好圆方树维护路径上最小值即可 方点的值为其儿子的最小值,这个用堆维护 为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆 这样充分利用 ...
- 【CF487E】Tourists(圆方树)
[CF487E]Tourists(圆方树) 题面 UOJ 题解 首先我们不考虑修改,再来想想这道题目. 我们既然要求的是最小值,那么,在经过一个点双的时候,走的一定是具有较小权值的那一侧. 所以说,我 ...
- 【学习笔记】圆方树(CF487E Tourists)
终于学了圆方树啦~\(≧▽≦)/~ 感谢y_immortal学长的博客和帮助 把他的博客挂在这里~ 点我传送到巨佬的博客QwQ! 首先我们来介绍一下圆方树能干什么呢qwq 1.将图上问题简化到树上问题 ...
- CF487E Tourists【圆方树+tarjan+multiset+树剖+线段树】
圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...
随机推荐
- Vmware安装CentOs7+gitlab(一)
本篇文章主要介绍了VMware安装Centos7超详细过程(图文),具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.软硬件准备 软件:推荐使用VMwear,我用的是VMwear 12 镜像:Ce ...
- Bootstrap实现注册界面
样式一 例图 代码 <head> <meta charset="UTF-8"> <title>用户注册</title> <li ...
- Webpack4教程 - 第三部分,如何使用插件
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/07/23/webpack-4-course-part ...
- Canvas 绘图学习笔记2
1 绘制文本 fillText(string,x,y,maxWidth) //填充试绘制文本 strokeText(string,x,y,maxWidth) 画线试绘制文本 设置字体样式: cont ...
- 通过 Sqoop1.4.7 将 Mysql5.7、Hive2.3.4、Hbase1.4.9 之间的数据导入导出
目录 目录 1.什么是 Sqoop? 2.下载应用程序及配置环境变量 2.1.下载 Sqoop 1.4.7 2.2.设置环境变量 2.3.设置安装所需环境 3.安装 Sqoop 1.4.7 3.1.修 ...
- Java Web相关问题
关于这两天主要问题的解答: (1) 驱动程序无法使用安全套接字层(SSL)加密与 SQL Server 建立安全连接.错误: java.lang.RuntimeException: Could no ...
- C# 霍尼韦尔扫码枪扫码打印
程序运行背景条件: 1.将扫码枪调制串口驱动模式 2.将扫码枪所在串口拆分成几个虚拟串口 3.扫码枪扫描条码就打印条码 4.WinForm程序 条码控件使用 DevExpress.XtraEditor ...
- Django学习笔记(1)--第一个项目
操作系统:Windows Python版本:python3.6 前置工作: pip install virtualenvwrapper #安装虚拟环境管理包 1.创建虚拟环境 mkvirtualenv ...
- ESP8266最小系统
http://www.dnsj88.com/Products/esp12f.html https://gitai.me/2017/04/Re-Zero-Starting-in-IoT/
- vuex直接修改state 与 用dispatch/commit来修改state的差异
一. 使用vuex修改state时,有两种方式: 1.可以直接使用 this.$store.state.变量 = xxx; 2.this.$store.dispatch(actionType, pay ...