CF487E Tourists - Tarjan缩点 + 树剖 + multiset
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的更多相关文章
- CF487E Tourists【圆方树+tarjan+multiset+树剖+线段树】
圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...
- CF487E Tourists 【圆方树 + 树剖 + 堆】
题目链接 CF487E 题解 圆方树 + 树剖 裸题 建好圆方树维护路径上最小值即可 方点的值为其儿子的最小值,这个用堆维护 为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆 这样充分利用 ...
- CF487E Tourists(圆方树+堆+链剖)
本题解并不提供圆方树讲解. 所以不会圆方树的出门右转问yyb 没有修改的话圆方树+链剖. 方点的权值为点双连通分量里的最小值. 然后修改的话圆点照修,每一个方点维护一个小根堆. 考虑到可能被菊花卡死. ...
- poj3694 Network[边双缩点+树剖/并查集]
首先同一个点双内部的加边肯定不影响..所以先缩点成树,然后每次加一条边,这条对应的树上路径上所有边就都不是桥了,且每次操作独立作用,不相互影响(不过有可能本来一条边已经不是桥了又被标记了一次),所以每 ...
- cf1000E We Need More Bosses (tarjan缩点+树的直径)
题意:无向联通图,求一条最长的路径,路径长度定义为u到v必须经过的边的个数 如果把强联通分量都缩成一个点以后,每个点内部的边都是可替代的:而又因为这是个无向图,缩完点以后就是棵树,跑两遍dfs求直径即 ...
- F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解
题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...
- LUOGU P2416 泡芙 (缩点+树剖)
传送门 解题思路 首先先缩点,然后将缩完点的权值改成点中路径为1的条数,然后再将边权下放到点权上,求一个每个点到根的路径和,然后用树上2点距离公式算..刚开始写的线段树,T了2个点. #include ...
- HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...
- CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...
随机推荐
- Promise.then
[Promise.then] 1.If onFulfilled returns a promise, the return value of then will be resolved/rejecte ...
- native和webview切换
native和webview 标签(空格分隔): native和webview 现在目前大部分的app都是native和webview混合,对应的native上的元素可以通过uiautomatorvi ...
- metasploit framework(六):信息收集
nmap 扫描 扫描完毕之后,hosts查看扫描的结果 auxiliary 扫描 使用arpsweep模块扫描 查看设置 设置网卡和目标IP 设置伪造的源IP和源MAC set SHOST <伪 ...
- hibernate mysql视图操作
hibernate对视图操作,首先建立数据库视图 视图v_invite: create view pintu.v_invite asselect cp.user_id as be_user_id,ca ...
- spark快速开发之scala基础之2控制流程
判断结构 大体与java相当.scala没有三元表达式. val num = if(1>0) 1 else 0 //相当于匿名函数 println(num) var num2 = 0 if(1& ...
- PHPActiveRecord 学习一
#连接数据库 <?phprequire_once dirname(__FILE__) . '/../../ActiveRecord.php'; // initialize ActiveRecor ...
- python计算两个数的百分比
a和b是整数,计算a/b的百分比 a=3 b=7 a=float(a) b=float(b) 保留百分比后2位小数 print "%.2f%%" % (a/b*100) '42. ...
- 设置https以及http转https的问题
公司用的是阿里云服务器win2008server r2 ,环境是phpwamp,出现许多问题.2018-11-12 一 设置https 1.设置httpd.ini 取消以下三个配置的# LoadMod ...
- 激活 pycharm
step1: 在本地 hosts 文件增加一行,windows 路径一般为:C:\Windows\System32\drivers\etc step2: 输入激活码 7SPIY8PDT7-eyJsaW ...
- openstack(Pike 版)集群部署(六)--- Horizon 部署
一.介绍 参照官网部署:https://docs.openstack.org/horizon/pike/install/ 继续上一博客进行部署:http://www.cnblogs.com/we ...