Solution

先Tarjan求出点双联通分量 并缩点。 用$multiset$维护 点双内的最小点权。

容易发现, 点双内的最小点权必须包括与它相连的割边的点权。 所以我们必须想办法来维护。

所以考虑用割点的点权更新它的父节点, 这样查询 点双 内的最小点权只需要查询本身的 $multiset$ 和 它的父亲节点就可以了。

最后加个树剖就能过啦!

Code

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#define rd read()
using namespace std; const int N = 2e5 + ;
const int inf = ~0U >> ; int Head[N << ], Tot;
int head[N], tot;
int low[N], dfn[N], cnt, col, c[N], nd_num, cut[N];
int st[N], tp;
int n, m, Q, a[N];
int f[N << ], top[N << ], sz[N << ], son[N << ], mk, id[N << ], dep[N << ]; vector<int> q[N];
multiset<int> S[N << ]; struct edge {
int nxt, to;
}e[N << ], E[N << ]; int read() {
int X = , p = ; char c = getchar();
for (; c > '' || c < ''; c = getchar())
if (c == '-') p = -;
for (; c >= '' && c <= ''; c = getchar())
X = X * + c - '';
return X * p;
} void add(int u, int v) {
e[++tot].to = v;
e[tot].nxt = head[u];
head[u] = tot;
} void Add(int u, int v) {
E[++Tot].to = v;
E[Tot].nxt = Head[u];
Head[u] = Tot;
} void tarjan(int u) {
low[u] = dfn[u] = ++cnt;
st[++tp] = u;
int flag = ;
for (int i = head[u]; i; i = e[i].nxt) {
int nt = e[i].to;
if (!dfn[nt]) {
tarjan(nt);
low[u] = min(low[u], low[nt]);
if (low[nt] < dfn[u])
continue;
col++; flag++;
cut[u] = ;
for (; tp;) {
int z = st[tp--];
q[col].push_back(z);
if (z == nt)
break;
}
q[col].push_back(u);
}
else low[u] = min(low[u], dfn[nt]);
}
if (flag < && u == )
cut[u] = ;
} namespace SegT { int MIN[N << ]; #define mid ((l + r) >> 1)
#define lson nd << 1
#define rson nd << 1 | 1 void up(int nd) {
MIN[nd] = min(MIN[lson], MIN[rson]);
} void modify(int pos, int d, int l, int r, int nd) {
if (l == r) {
MIN[nd] = d;
return;
}
if (pos <= mid)
SegT::modify(pos, d, l, mid, lson);
else
SegT::modify(pos, d, mid + , r, rson);
SegT::up(nd);
}
int query(int L, int R, int l, int r, int nd) {
if (L <= l && r <= R)
return MIN[nd];
int tmp = inf;
if(L <= mid)
tmp = min(tmp, SegT::query(L, R, l, mid, lson));
if(mid < R)
tmp = min(tmp, SegT::query(L, R, mid + , r, rson));
return tmp;
} #undef mid
#undef lson
#undef rson
} namespace SP { void dfs1(int u) {
sz[u] = ;
for (int i = Head[u]; i; i = E[i].nxt) {
int nt = E[i].to;
if (nt == f[u])
continue;
f[nt] = u;
dep[nt] = dep[u] + ;
SP::dfs1(nt);
sz[u] += sz[nt];
if(sz[nt] >= sz[son[u]])
son[u] = nt;
}
} void dfs2(int u) {
id[u] = ++mk;
if (!son[u])
return;
top[son[u]] = top[u];
SP::dfs2(son[u]);
for (int i = Head[u]; i; i = E[i].nxt) {
int nt = E[i].to;
if (nt == f[u] || nt == son[u])
continue;
top[nt] = nt;
SP::dfs2(nt);
}
} int query(int x, int y) {
int re = inf, tmp;
for (; top[x] != top[y];) {
if (dep[top[x]] < dep[top[y]])
swap(x, y);
tmp = SegT::query(id[top[x]], id[x], , mk, );
re = min(tmp, re);
x = f[top[x]];
}
if (dep[x] < dep[y])
swap(x, y);
tmp = SegT::query(id[y], id[x], , mk, );
re = min(tmp, re);
if (f[y] && y <= col)
tmp = SegT::query(id[f[y]], id[f[y]], , mk, );
re = min(tmp, re);
return re;
}
} int main()
{
n = rd; m = rd; Q = rd;
for (int i = ; i <= n; ++i)
a[i] = rd;
for (int i = ; i <= m; ++i) {
int u = rd, v = rd;
add(u, v); add(v, u);
}
tarjan();
nd_num = col;
for (int i = ; i <= n; ++i)
if (cut[i]) c[i] = ++nd_num;
for (int i = ; i <= col; ++i)
for (int j = , len = q[i].size(); j < len; ++j) {
int x = q[i][j];
if (cut[x])
Add(c[x], i), Add(i, c[x]);
else c[x] = i;
}
dep[] = ;
SP::dfs1();
top[] = ;
SP::dfs2();
for (int i = ; i <= n; ++i) {
int x = c[i];
S[x].insert(a[i]);
if(x > col)
S[f[x]].insert(a[i]);
}
for (int i = ; i <= nd_num; ++i) {
int x = *S[i].begin();
SegT::modify(id[i], x, , mk, );
}
for (; Q; Q--) {
char ch = getchar();
while (ch != 'A' && ch != 'C')
ch = getchar();
int u = rd, v = rd;
if (ch == 'C') {
swap(v, a[u]);
S[c[u]].erase(S[c[u]].find(v));
S[c[u]].insert(a[u]);
int x = *S[c[u]].begin();
SegT::modify(id[c[u]], x, , mk, );
if (c[u] <= col)
continue;
S[f[c[u]]].erase(S[f[c[u]]].find(v));
S[f[c[u]]].insert(a[u]);
x = *S[f[c[u]]].begin();
SegT::modify(id[f[c[u]]], x, , mk, );
}
else {
if (u == v) printf("%d\n", a[u]);
else printf("%d\n", SP::query(c[u], c[v]));
}
}
}

CF487E Tourists - Tarjan缩点 + 树剖 + multiset的更多相关文章

  1. CF487E Tourists【圆方树+tarjan+multiset+树剖+线段树】

    圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...

  2. CF487E Tourists 【圆方树 + 树剖 + 堆】

    题目链接 CF487E 题解 圆方树 + 树剖 裸题 建好圆方树维护路径上最小值即可 方点的值为其儿子的最小值,这个用堆维护 为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆 这样充分利用 ...

  3. CF487E Tourists(圆方树+堆+链剖)

    本题解并不提供圆方树讲解. 所以不会圆方树的出门右转问yyb 没有修改的话圆方树+链剖. 方点的权值为点双连通分量里的最小值. 然后修改的话圆点照修,每一个方点维护一个小根堆. 考虑到可能被菊花卡死. ...

  4. poj3694 Network[边双缩点+树剖/并查集]

    首先同一个点双内部的加边肯定不影响..所以先缩点成树,然后每次加一条边,这条对应的树上路径上所有边就都不是桥了,且每次操作独立作用,不相互影响(不过有可能本来一条边已经不是桥了又被标记了一次),所以每 ...

  5. cf1000E We Need More Bosses (tarjan缩点+树的直径)

    题意:无向联通图,求一条最长的路径,路径长度定义为u到v必须经过的边的个数 如果把强联通分量都缩成一个点以后,每个点内部的边都是可替代的:而又因为这是个无向图,缩完点以后就是棵树,跑两遍dfs求直径即 ...

  6. F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解

    题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...

  7. LUOGU P2416 泡芙 (缩点+树剖)

    传送门 解题思路 首先先缩点,然后将缩完点的权值改成点中路径为1的条数,然后再将边权下放到点权上,求一个每个点到根的路径和,然后用树上2点距离公式算..刚开始写的线段树,T了2个点. #include ...

  8. HDU4612+Tarjan缩点+BFS求树的直径

    tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...

  9. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

随机推荐

  1. js高级-面向对象继承

    一.工厂模式创建对象及优缺点 继承就是把公共的部分抽象出来作为父类,基类.吃饭,跑步等 var a = {}; //批量创建不方便,不能重复设置公共属性的代码 //工厂模式出现了,创建10个Cat对象 ...

  2. 关于python中的is和==的区别

    Python 中的比较:is 与 ==   在 Python 中会用到对象之间比较,可以用 ==,也可以用 is .但是它们的区别是什么呢? is 比较的是两个实例对象是不是完全相同,它们是不是同一个 ...

  3. Hibernate一对多单向关联和双向关联映射方法及其优缺点 (待续)

    一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同.它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的同 ...

  4. springboot1 缓存前端

    @Configurationpublic class WebMvcConfig extends WebMvcConfigurerAdapter { public void addResourceHan ...

  5. modal template

    <div class="modal fade" id="tmp_order_modal" tabindex="-1" role=&qu ...

  6. centos 7 搭建openvpn-2.4.6

    参考:https://blog.csdn.net/weixin_42250094/article/details/80384863 http://www.startupcto.com/server-t ...

  7. as3.0去除空格

    var str:String="是 我们 呀CuPlay er.com网站" function trim(string:String):String { return string ...

  8. mysql windows安装资源

    压缩包资源 https://mirrors.tuna.tsinghua.edu.cn/mysql/downloads/MySQL-5.7/ 配置流程 https://blog.csdn.net/hel ...

  9. c++ sizeof,strlen, length

    #include <map>#include <iostream>#include <algorithm>#include <functional>#i ...

  10. sqlserver还原数据库失败,sql2008备份集中的数据库备份与现有的xxx数据库不同

    正常操作发现报标题错误,百度后解决思路如下(@参考文章)转到选项下面,勾选覆盖现有数据库即可