【CF487E】Tourists
题意
给定一张无向图,点有点权,多次询问两点之间路径上点权最小的点的可能的最小值,支持修改点权。
Sol
一棵树就很简单 , 于是我们考虑点双(环)上的情况 , 直观想法就是缩完点双后一个点双的权值直接就是其中的最小值 , 这样我们要讨论的就是路径的起始端可能是在割点上的情况。
直接建一个广义圆方树就没有什么要多考虑的了。
把每一个点双找出来新建方点来代表。这样在圆方树上过了方点就相当与可以在点双里面随便走 , 那么方点的点权自然就是点双里所有点的点权的最小值了。
路径询问和修改点权就用个树剖+线段树。
不过这样的话修改一个圆点的点权时我们要修改它儿子集合的所有方点 , 复杂度就爆炸了。
所以我们对于一个方点不考虑它父亲的权值就行了,那么一个方点的权值就是去掉父亲圆点之后的点双上的点的权值的最小值。只需要最后如果两个点的 LCA 是一个方点的话把他的父亲圆点的权值也用来更新答案就好了。
所以我们还需要一个 可删除堆/multiset 来解决点权的变化问题。
要注意的一点是 , 对于桥边不要新建方点 , 容易被卡。
code:
#include<bits/stdc++.h>
using namespace std;
#define Set(a,b) memset(a,b,sizeof(a))
template<class T>inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}
int n,m,q;
const int N=1e5+10;
struct edge{int to,next;}a[N<<1];
int val[N],head[N],cnt=0;
inline void add(int x,int y){a[cnt]=(edge){y,head[x]};head[x]=cnt++;}
typedef pair<int,int> PA;
int Tn;
struct Heap{
priority_queue<int> P,Q;
inline void Delete(const int x){P.push(-x);}
inline void push(const int x){Q.push(-x);}
inline int top(){while(!P.empty()&&!Q.empty()&&P.top()==Q.top()) P.pop(),Q.pop();return -Q.top();}
}H[N];
namespace Tree{
const int N=2e5+10;
edge a[N<<1];int head[N],cnt=0,son[N],size[N],top[N],id[N],fa[N],dep[N],I=0,dfn[N];
inline void add(int x,int y){a[++cnt]=(edge){y,head[x]};head[x]=cnt;}
void dfs(int u){
size[u]=1;
for(int v,i=head[u];i;i=a[i].next){
v=a[i].to;if(v==fa[u]) continue;
fa[v]=u;dep[v]=dep[u]+1;dfs(v);
size[u]+=size[v];
if(!son[u]||size[son[u]]<size[v]) son[u]=v;
}return;
}
void Dfs(int u,int tp){
id[u]=++I;dfn[I]=u;top[u]=tp;
if(!son[u]) return;Dfs(son[u],tp);
for(int v,i=head[u];i;i=a[i].next) {
v=a[i].to;if(v==fa[u]||v==son[u]) continue;
Dfs(v,v);
}return;
}
#define ls (u<<1)
#define rs (u<<1|1)
int Mi[N<<2];
inline void update(int u){Mi[u]=min(Mi[ls],Mi[rs]);return;}
void Build(int u,int l,int r){
if(l==r) return void(Mi[u]=val[dfn[l]]);
int mid=l+r>>1;Build(ls,l,mid),Build(rs,mid+1,r);
return update(u);
}
inline void Prework(){dfs(1);Dfs(1,1);Build(1,1,n);}
int Query(int u,int l,int r,int L,int R){
if(l>=L&&r<=R) return Mi[u];int mid=l+r>>1;
if(mid>=R) return Query(ls,l,mid,L,R);
if(mid< L) return Query(rs,mid+1,r,L,R);
return min(Query(ls,l,mid,L,mid),Query(rs,mid+1,r,mid+1,R));
}
inline int Query(int u,int v){
if(u==v) return val[u];
int ans=min(val[u],val[v]);
while(top[u]^top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans=min(ans,Query(1,1,I,id[top[u]],id[u]));
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);int lca=u;
ans=min(ans,Query(1,1,I,id[u],id[v]));
if(lca>Tn) ans=min(ans,val[fa[lca]]);
return ans;
}
void Modify(int u,int l,int r,int p,int x){
if(l==r) return void(Mi[u]=x);
int mid=l+r>>1;
if(mid>=p) Modify(ls,l,mid,p,x);
else Modify(rs,mid+1,r,p,x);
update(u);
}
inline void Modify(int u,int w){
int f=fa[u];Modify(1,1,I,id[u],w);
int vu=val[u];val[u]=w;
if(f>Tn) {
int ID=f-Tn;
H[ID].Delete(vu);H[ID].push(w);
int nw=H[ID].top();
if(val[f]!=nw) val[f]=nw,Modify(1,1,I,id[f],nw);
}
}
}
#undef ls
#undef rs
PA stk[N];int bel[N],bcc=0,dfn[N],low[N],I=0,top=0;
void tarjan(int u,int ret) {
dfn[u]=low[u]=++I;
for(int v,i=head[u];~i;i=a[i].next){
v=a[i].to;if(ret==(i^1)) continue;
if(!dfn[v]) {
stk[++top]=PA(u,v);int nowt=top;
tarjan(v,i);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u]) {
if(top!=nowt){
++bcc;++n;Tree::add(u,n);
while(top) {
int p=stk[top].first,q=stk[top].second;--top;
if(bel[p]!=bcc) {
bel[p]=bcc;
if(p^u) Tree::add(n,p),H[bcc].push(val[p]);
}
if(bel[q]!=bcc) {
bel[q]=bcc;
if(q^u) Tree::add(n,q),H[bcc].push(val[q]);
}
if(p==u&&q==v) break;
}
val[n]=H[bcc].top();
}
else --top,Tree::add(u,v);
}
}
else if(dfn[v]<dfn[u]) {stk[++top]=PA(u,v);low[u]=min(low[u],dfn[v]);}
}
}
int main()
{
init(n),init(m),init(q);Set(head,-1);Tn=n;
for(int i=1;i<=n;++i) init(val[i]);int u,v;
for(int i=1;i<=m;++i) {init(u),init(v);add(u,v),add(v,u);}
tarjan(1,-1);Tree::Prework();
for(int i=1;i<=q;++i) {
char ch=getchar();while(ch!='C'&&ch!='A') ch=getchar();
int a,w,b;
if(ch=='C') {init(a),init(w);Tree::Modify(a,w);}
else {init(a),init(b);printf("%d\n",Tree::Query(a,b));}
}
return 0;
}
【CF487E】Tourists的更多相关文章
- 【CF487E】Tourists(圆方树)
[CF487E]Tourists(圆方树) 题面 UOJ 题解 首先我们不考虑修改,再来想想这道题目. 我们既然要求的是最小值,那么,在经过一个点双的时候,走的一定是具有较小权值的那一侧. 所以说,我 ...
- 【POJ1823】【线段树】Hotel
Description The "Informatics" hotel is one of the most luxurious hotels from Galaciuc. A l ...
- hihoCoder 1578 Visiting Peking University 【贪心】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛)
#1578 : Visiting Peking University 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Ming is going to travel for ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【调侃】IOC前世今生
前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...
- Python高手之路【三】python基础之函数
基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...
随机推荐
- Sass 的 & 符号(ampersands)
重复声明 有时您需要击败第三方 CSS 库的声明来获取样式的所有权: .parent.parent {} 这种方式比使用和 ID,内联样式或!important的压倒性弱,并且它可能比使用任意父元素限 ...
- hdu 4758 (AC自动机)
除了走到哪里,还要加状态表示当前节点和已经匹配的串 #include<iostream> #include<cstdio> #include<string> #in ...
- spring(二) AOP注入
AOP概念 l AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码 l 经典应用:事务管理.性能监视.安全检查.缓存 .日志等 l Spring AOP使用纯Java实现,不需要专门的编译 ...
- 【SD系列】SAP SD凭证处理被批次处理冻结
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[SD系列]SAP SD凭证处理被批次处理冻结 ...
- 【Python】我的第一个豆瓣短评爬虫
写在开头 豆瓣上有着大量的影视剧的评论,所以说,要是想要实现对广大人民群众的观点的分析,对一部片子的理解,综合来看大家的评论是很有必要的.而短评作为短小精干的快速评论入口,是值得一谈的. 所以先要实现 ...
- jenkins初级使用篇
1.jenkins的初级使用 1.1 介绍 创建一个项目 可以看到当前登陆用户及用户权限 可以查看到所有构建过的项目的历史 系统管理 My Views:视图功能,我们可以自己创建一个自己的视图 系统管 ...
- [百家号]APT组织简介2019
5家新APT组织被披露,2019是“后起之秀”的天下? https://baijiahao.baidu.com/s?id=1621699899936470038&wfr=spider& ...
- linux中文件IO
一. linux常用文件IO接口 1.1. 文件描述符 1.1.1. 文件描述符的本质是一个数字,这个数字本质上是进程表中文件描述符表的一个表项,进程通过文件描述符作为index去索引查表得到文件表指 ...
- 提高CUI测试稳定性技术
GUI自动化测试稳定性,最典型的表现形式就是,同样的测试用例在同样的环境上,时而测试通 过,时而测试失败. 这也是影响GUI测试健康发展的一个重要障碍,严重降低了GUI测试的可信性. 五种造成GUI测 ...
- PHP实现支付宝小程序用户授权的工具类
背景 最近项目需要上线支付宝小程序,同时需要走用户的授权流程完成用户信息的存储,以前做过微信小程序的开发,本以为实现授权的过程是很简单的事情,但是再实现的过程中还是遇到了不少的坑,因此记录一下实现的过 ...