Solution -「CF 487E」Tourists
\(\mathcal{Description}\)
Link.
维护一个 \(n\) 个点 \(m\) 条边的简单无向连通图,点有点权。\(q\) 次操作:
- 修改单点点权。
- 询问两点所有可能路径上点权的最小值。
\(n,m,q\le10^5\)。
\(\mathcal{Solution}\)
怎么可能维护图嘛,肯定是维护圆方树咯!
一个比较 naive 的想法是,每个方点维护其邻接圆点的最小值,树链剖分处理询问。
不过修改的复杂度会由于菊花退化:修改”花蕊“的圆点,四周 \(\mathcal O(n)\) 个方点的信息都需要修改。
联想到 array 这道题,我们尝试”弱化“方点所维护的信息。每个方点,维护其圆方树上儿子们的点权最小值。那么每次修改圆点,至多就只有其父亲需要修改信息了。
于是,每个方点用 std::multiset 或者常见的双堆 trick 维护最小值信息(推荐后者,常数较小),再用一样的树剖处理询问即可。
复杂度 \(\mathcal O(n\log^2n)\)。
\(\mathcal{Code}\)
#include <queue>
#include <cstdio>
#define adj( g, u, v ) \
for ( int eid = g.head[u], v; v = g.to[eid], eid; eid = g.nxt[eid] )
const int MAXN = 2e5, MAXM = 4e5;
int n, m, q, val[MAXN + 5], snode;
int dfc, tp, dfn[MAXN + 5], low[MAXN + 5], stk[MAXN + 5];
int siz[MAXN + 5], dep[MAXN + 5], fa[MAXN + 5], son[MAXN + 5];
int top[MAXN + 5];
inline bool chkmin ( int& a, const int b ) { return b < a ? a = b, true : false; }
struct Graph {
int ecnt, head[MAXN + 5], to[MAXM + 5], nxt[MAXM + 5];
inline void link ( const int s, const int t ) {
to[++ ecnt] = t, nxt[ecnt] = head[s];
head[s] = ecnt;
}
inline void add ( const int u, const int v ) {
link ( u, v ), link ( v, u );
}
} src, tre;
struct Heap {
std::priority_queue<int, std::vector<int>, std::greater<int> > val, rem;
inline void push ( const int ele ) { val.push ( ele ); }
inline void pop ( const int ele ) { rem.push ( ele ); }
inline int top () {
for ( ; ! val.empty () && ! rem.empty () && val.top () == rem.top (); val.pop (), rem.pop () );
return val.empty () ? -1 : val.top ();
}
} heap[MAXN * 2 + 5];
struct SegmentTree {
int mn[MAXN << 3];
inline void pushup ( const int rt ) { chkmin ( mn[rt] = mn[rt << 1], mn[rt << 1 | 1] ); }
inline void update ( const int rt, const int l, const int r, const int x, const int v ) {
if ( l == r ) return void ( mn[rt] = v );
int mid = l + r >> 1;
if ( x <= mid ) update ( rt << 1, l, mid, x, v );
else update ( rt << 1 | 1, mid + 1, r, x, v );
pushup ( rt );
}
inline int query ( const int rt, const int l, const int r, const int ql, const int qr ) {
if ( ql <= l && r <= qr ) return mn[rt];
int ret = 2e9, mid = l + r >> 1;
if ( ql <= mid ) chkmin ( ret, query ( rt << 1, l, mid, ql, qr ) );
if ( mid < qr ) chkmin ( ret, query ( rt << 1 | 1, mid + 1, r, ql, qr ) );
return ret;
}
} st;
inline void Tarjan ( const int u, const int f ) {
dfn[u] = low[u] = ++ dfc, stk[++ tp] = u;
adj ( src, u, v ) if ( v ^ f ) {
if ( ! dfn[v] ) {
Tarjan ( v, u ), chkmin ( low[u], low[v] );
if ( low[v] >= dfn[u] ) {
tre.add ( u, ++ snode );
do {
tre.add ( snode, stk[tp] );
heap[snode].push ( val[stk[tp]] );
} while ( stk[tp --] ^ v );
}
} else chkmin ( low[u], dfn[v] );
}
}
inline void DFS1 ( const int u, const int f ) {
dep[u] = dep[fa[u] = f] + 1, siz[u] = 1;
adj ( tre, u, v ) if ( v ^ f ) {
DFS1 ( v, u ), siz[u] += siz[v];
if ( siz[v] > siz[son[u]] ) son[u] = v;
}
}
inline void DFS2 ( const int u, const int tp ) {
top[u] = tp, dfn[u] = ++ dfc;
if ( son[u] ) DFS2 ( son[u], tp );
adj ( tre, u, v ) if ( v ^ fa[u] && v ^ son[u] ) DFS2 ( v, v );
}
inline int queryChain ( int u, int v ) {
int ret = 2e9;
while ( top[u] ^ top[v] ) {
if ( dep[top[u]] < dep[top[v]] ) u ^= v ^= u ^= v;
chkmin ( ret, st.query ( 1, 1, snode, dfn[top[u]], dfn[u] ) );
u = fa[top[u]];
}
if ( dep[u] < dep[v] ) u ^= v ^= u ^= v;
chkmin ( ret, st.query ( 1, 1, snode, dfn[v], dfn[u] ) );
if ( v > n && fa[v] ) chkmin ( ret, val[fa[v]] );
return ret;
}
int main () {
scanf ( "%d %d %d", &n, &m, &q ), snode = n;
for ( int i = 1; i <= n; ++ i ) scanf ( "%d", &val[i] );
for ( int i = 1, u, v; i <= m; ++ i ) {
scanf ( "%d %d", &u, &v );
src.add ( u, v );
}
Tarjan ( 1, 0 ), dfc = 0;
DFS1 ( 1, 0 ), DFS2 ( 1, 1 );
for ( int i = 1; i <= n; ++ i ) st.update ( 1, 1, snode, dfn[i], val[i] );
for ( int i = n + 1; i <= snode; ++ i ) st.update ( 1, 1, snode, dfn[i], heap[i].top () );
char op[5]; int a, b;
for ( ; q --; ) {
scanf ( "%s %d %d", op, &a, &b );
if ( op[0] == 'C' ) {
st.update ( 1, 1, snode, dfn[a], b );
if ( fa[a] ) {
heap[fa[a]].pop ( val[a] );
heap[fa[a]].push ( b );
st.update ( 1, 1, snode, dfn[fa[a]], heap[fa[a]].top () );
}
val[a] = b;
} else {
printf ( "%d\n", queryChain ( a, b ) );
}
}
return 0;
}
Solution -「CF 487E」Tourists的更多相关文章
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
- Solution -「CF 1622F」Quadratic Set
\(\mathscr{Description}\) Link. 求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...
- Solution -「CF 923F」Public Service
\(\mathscr{Description}\) Link. 给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...
- Solution -「CF 923E」Perpetual Subtraction
\(\mathcal{Description}\) Link. 有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...
- Solution -「CF 1586F」Defender of Childhood Dreams
\(\mathcal{Description}\) Link. 定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...
- Solution -「CF 1237E」Balanced Binary Search Trees
\(\mathcal{Description}\) Link. 定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...
- Solution -「CF 623E」Transforming Sequence
题目 题意简述 link. 有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...
- Solution -「CF 1023F」Mobile Phone Network
\(\mathcal{Description}\) Link. 有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...
- Solution -「CF 599E」Sandy and Nuts
\(\mathcal{Description}\) Link. 指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...
随机推荐
- Shell 里空语句怎么写 - 半角的冒号
Python 里的空语句写作pass for x in range(10): pass Shell 里的空语句写作 : #!/bin/bash for x in {1..10} do #echo $x ...
- java 关于 重写、覆写、覆盖、重载 的总结【不想再傻傻分不清了】
1.前言 有些东西,名称不同,其实就是一个东西,你说是扯淡不? 2.重写 重写,又叫覆写.覆盖 ,注解@Override,词义为推翻 , 用法特点是继承父类后,重写的父类方法名字.参数.返回值必须相同 ...
- ssh到localhost或127.0.0.1拒绝连接
通过ssh连接到本机报错 ssh: connect to host localhost port 22: Connection refused, 你能用ssh登录其它主机并不代表着本地有ssh服务,要 ...
- 拓展 Array 方法
为 Array 对象扩展了一个迭代器之后,就可以利用这个法代器进一步拓展 Array 的方法,使其能够完成更多的实用功能. Array.prototype.each = function( f ) { ...
- layui父表单获取子表单的值完成修改操作
最近在做项目时,学着用layui开发后台管理系统. 但在做编辑表单时遇到了一个坑. 点击编辑时会出现一个弹窗. 我们需要从父表单传值给子表单.content是传值给子表单 layer.open({ t ...
- element ui table 表格排序
实现elementui表格的排序 1:给table加上sort-change,给table每一项加上sortable和column-key,排序是根据column-key来进行排序的 <el-t ...
- 【vps】如何在vps上安装mirai机器人?
[vps]如何在vps上安装mirai机器人? 前言 由于某位师傅在群里设置了一个bot,吸引了我,所以我之前找他问了点bot的相关知识,这几天正好服务器搬迁,所以就在新服务器上再装一遍bot 1.安 ...
- 云计算——实验一 HDFS与MAPREDUCE操作
1.虚拟机集群搭建部署hadoop 利用VMware.centOS-7.Xshell(secureCrt)等软件搭建集群部署hadoop 远程连接工具使用Xshell: HDFS文件操作 2.1 HD ...
- 关于3G移动通信网络中用户ip的配置过程的研究(中国电信cdma2000)
在RP口对ppp过程进行研究 PPP协商过程,如下图所示: 在建立ppp过程中pdsn需要与FAAA.HAAA交互.同时在分组数据业务进行过程中这种交互更加频繁,介绍如下,分为两种情况,简单ip,移动 ...
- P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two
// Problem: P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two // Contest: Luogu // URL: https://www.luogu.com ...