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+树剖+线段树】
圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...
随机推荐
- PHP设计模式的六大设计原则
PHP设计模式的六大设计原则 1 简介 软件设计最大的难题就是应对需求的变化,但是纷繁复杂的需求变化却是不可预料的.此时,我们可以通过六大设计原则良好的应对未来的变化. 2 讲解 2.1 单一职责原则 ...
- Vue slot插槽
插槽用于内容分发,存在于子组件之中. 插槽作用域 父级组件作用域为父级,子级组件作用域为子级,在哪定义的作用域就在哪. 子组件之间的内容是在父级作用域的,无法直接访问子组件里面的数据. 插槽元素 &l ...
- 命令行操作mysql 未完待续......
复制数据表 create table 新表 like 旧表: 删除表中某个字段 alter table 表名 drop column 字段; 例子: alter table news_apply_lo ...
- Python网络爬虫-信息标记
信息标记的三种形式: XML(扩展标记语言) JSON(js中面向对象的信息表达形式,由类型的(string)键值对组成) "name":"北京理工大学" YA ...
- Linux下使用yum安装软件命令
1.yum list | grep 要下载的文件名字2.yum install 完整文件名字3.rpm -qa | grep 软件名字 //查看版本
- MySQL 基础知识梳理学习(七)----sync_binlog
一般在生产环境中,很少用MySQL单实例来支撑业务,大部分的MySQL应用都是采用搭建集群的方法.搭建MySQL集群,可以进行数据库层面的读写分离.负载均衡或数据备份.基于MySQL原生的Replic ...
- zookeeper 分布式锁原理
zookeeper 分布式锁原理: 1 大家也许都很熟悉了多个线程或者多个进程间的共享锁的实现方式了,但是在分布式场景中我们会面临多个Server之间的锁的问题,实现的复杂度比较高.利用基于googl ...
- C++ 精英化趋势
精英化趋势 C++ 是一门引起无数争议的语言.眼下最常听到的声音则是 C++ 将趋于没落,会被某某语言取代.我很怀疑这种论调的起点是商业宣传,C++ 的真实趋势应该是越来越倾向于精英化. 精英化是指在 ...
- Centos7修改yum源
1. 备份本地yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak 2.获取阿里yum源配置文 ...
- C# 菜单之递归算法
今天因为菜单的问题, 需要用到递归算法, 在此记录一下: 1.表结构如下:(这里只是展示两个比较重要的字段) ,大家应该都看明白 2.先定义一个菜单结构类. 3.实现递归. private List& ...