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+树剖+线段树】
圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...
随机推荐
- Java异常实战——OutOfMemoryError
在Java虚拟机规范描述中,除了程序计数器外,虚拟机内存的其他几个运行区域都有发生 OOM 异常的可能.在这里,用代码验证各个运行时区域存储的内容并讨论该如何进行处理 Java堆溢出 Java 堆用于 ...
- Android为TV端助力 listview与recyclerview上下联动
首先是主布局fragment里面的xml文件 <?xml version="1.0" encoding="utf-8"?><RelativeL ...
- 记一次zabbix排错(数据库安装在其它服务器上)
记一次zabbix排错 故障现象 1.在/var/log/zabbix/zabbix_server.log中出现以下报错: 12106:20190314:090947.010 [Z3001] conn ...
- WebApi发布到外网提示404问题
今天在做微信接口的对接,需要把webApi发布到服务器,放上去的时候,提示404 找了以后,发现了这段代码,粘贴上去就可以用了 在web.config添加如下节点 <system.webServ ...
- C# -- 使用 DriveInfo 获取磁盘驱动器信息
C# -- 使用 DriveInfo 获取磁盘驱动器信息 1. 代码实现 class Program { static void Main(string[] args) { GetComputerDi ...
- cocos web 多端口运行
cocos2d-js 也是比较普遍的游戏开发工具之一吧,今天想同时启动多个js项目来看下效果,结果百度不到添加端口的方法,又得去翻源码.... cocos run -p web 只要运行在本地就可以启 ...
- 解决consul覆盖注册
默认注册consul的服务id为服务名-端口号,相同的服务名和端口号注册会覆盖 解决方式: 1.自定义Consul注册Id import com.ecwid.consul.v1.ConsulClien ...
- Vue组件之全局组件与局部组件
1全局注册实例 <div id="app"> <com-btn></com-btn> <com-btn></com-btn&g ...
- BERT模型在多类别文本分类时的precision, recall, f1值的计算
BERT预训练模型在诸多NLP任务中都取得最优的结果.在处理文本分类问题时,即可以直接用BERT模型作为文本分类的模型,也可以将BERT模型的最后层输出的结果作为word embedding导入到我们 ...
- [LeetCode] 19. 删除链表的倒数第N个节点
题目链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/ 题目描述: 给定一个链表,删除链表的倒数第 n 个节点, ...