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+树剖+线段树】
圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...
随机推荐
- Spring MVC(三)控制器获取页面请求参数以及将控制器数据传递给页面和实现重定向的方式
首先做好环境配置 在mvc.xml里进行配置 1.开启组件扫描 2.开启基于mvc的标注 3.配置试图处理器 <?xml version="1.0" encoding=&qu ...
- WOW.js 使用教程
官网加动画特效,哇哦,下面我介绍一下WOW.js 官网地址:https://www.delac.io/wow/ 点击github可以找到wow.js和wow.min.js 以及animate.css者 ...
- 小程序应用的Python服务器部署高配,依然是腾讯云秒杀阿里云!
上一篇文章,“小程序创业最低配置部署,腾讯云折扣秒杀阿里云!”介绍了小程序项目启动时的最低配置服务器选择,但当项目良好发展时,还是要把服务器配置调整到标准水平,承受住日益增长的流量访问. 随着Pyth ...
- Django用户继承AbstractUser后密码为明文
Django用户继承AbstractUser后密码为明文 其实本不应该有这个问题,却花了我很久的时间,因为还是初学阶段. 造成这个原因是因为在admin注册的生活没有指定Admin 在app的admi ...
- android - TextView单行显示...或者文字左右滚动(走马灯效果)
条件 TextView单行显示,文字左右滚动(走马灯效果)实现条件: 实现单行设置固定宽度或者设置权重都行 代码 TextView滚动必须写下面几个属性 android:singleLine=&quo ...
- Android串口开发
参考资料: https://www.jianshu.com/p/9249ed03e745 GitHUb地址: https://github.com/AIlll/AndroidSerialPort An ...
- Linux(CentOS7)下如何配置多个JDK环境变量
一.Linux版本 二.复制粘贴多个JDK出来,如下 cp -R jdk1.7.0_80/ jdk1.7.0_80-2 cp -R jdk1.7.0_80/ jdk1.7.0_80-3 三.配置多个J ...
- (转)postman安装及简单使用
Postman安装与使用 2018-06-04 22:58 by 虫师, 46636 阅读, 10 评论, 收藏, 编辑 Postman一款非常流行的API调试工具.其实,开发人员用的更多.因为测试人 ...
- excel身份证验证(附带防止粘贴导致校验失效的函数)
一.检验函数 =IF(LEN(A1)=18,MID("10X98765432",MOD(SUMPRODUCT(MID(A1,ROW(INDIRECT("1:17" ...
- python学习——读取染色体长度(二、向前一步:通过染色体序列获得长度信息)
# 读取fasta # 解析每条序列的长度 chr1_seq = 'ATATATATAT' chr2_seq = 'ATATATATATCGCGCGCGCG' chr3_seq = 'ATATATAT ...