UOJ #30【CF Round #278】Tourists
求从$ x$走到$ y$的路径上可能经过的最小点权,带修改 UOJ #30
$ Solution:$
如果两个点经过了某个连通分量,一定可以走到这个连通分量的最小值
直接构建圆方树,圆点存原点的点权,方点用$ multiset$存连通分量的点权集合,权值为集合中的最小值
每次询问就变成求圆方树中一条树链的最小值,可以用树链剖分维护
考虑修改一个圆点的点权
对于这个圆点直接修改,但如果暴力修改周围方点,复杂度明显爆炸
我们修改一下方点的定义,改为这个连通分量中除了自己父亲圆点外其他圆点的最小权值
这样修改一个圆点的权值的时候只需要这个圆点的父亲方点的权值
每次询问的时候如果$ LCA$为方点还要额外考虑这个方点的父亲圆点的贡献
这样就可以在$ O(n log^2 n)$的时间复杂度内解决这个问题
$ my \ code:$
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#define M 200010
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x = ; char zf = ; char ch = getchar();
while (ch != '-' && !isdigit(ch)) ch = getchar();
if (ch == '-') zf = -, ch = getchar();
while (isdigit(ch)) x = x * + ch - '', ch = getchar(); return x * zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int i,j,k,m,n,x,y,z,cnt;
int F[M],L[M],N[M],a[M],c[M],dfn[M],low[M],w[M],v[M];
void add(int x,int y){
a[++k]=y;
if(!F[x])F[x]=k;
else N[L[x]]=k;
L[x]=k;
}
int sta[M],top;
vector<int>e[M];
multiset<int>s[M];
void Add(int x,int y){
e[x].push_back(y);
e[y].push_back(x);
}
void tarjan(int x){
dfn[x]=low[x]=++cnt;sta[++top]=x;
for(rt i=F[x];i;i=N[i]){
if(!dfn[a[i]]){
tarjan(a[i]),low[x]=min(low[x],low[a[i]]);
if(low[a[i]]>=dfn[x]){
n++;
while(sta[top+]!=a[i])s[n].insert(w[sta[top]]),Add(sta[top--],n);
Add(x,n);
if(!s[n].size())w[n]=;else w[n]=*s[n].begin();
}
}
low[x]=min(low[x],dfn[a[i]]);
}
}
char getopt(){
char c=getchar();
while(c!='A'&&c!='C')c=getchar();
return c;
}
int size[M],deep[M],fa[M],to[M],up[M],pl[M],NN;
void dfs(int x,int pre){
size[x]=;fa[x]=pre;
for(auto i:e[x])if(i!=pre)deep[i]=deep[x]+,dfs(i,x),size[x]+=size[i];
}
void dfs2(int x,int chain){
dfn[x]=++cnt;to[cnt]=x;int heavy=;up[x]=chain;
for(auto i:e[x])if(i!=fa[x])if(size[i]>size[heavy])heavy=i;
if(!heavy)return;
dfs2(heavy,chain);
for(auto i:e[x])if(i!=heavy&&i!=fa[x])dfs2(i,i);
}
struct seg{
int L,R,Min;
}t[M*];
void build(int x,int L,int R){
t[x].L=L;t[x].R=R;
if(L==R)return t[x].Min=w[to[L]],pl[to[L]]=x,void();
const int mid=L+R>>;
build(x<<,L,mid);build(x<<|,mid+,R);
t[x].Min=min(t[x<<].Min,t[x<<|].Min);
}
inline int min(const int &x,const int &y){
return x<y?x:y;
}
int query(int x,int L,int R){
if(t[x].L>=L&&t[x].R<=R)return t[x].Min;
const int mid=t[x].L+t[x].R>>;
if(R<=mid)return query(x<<,L,R);
if(L>mid)return query(x<<|,L,R);
return min(query(x<<,L,R),query(x<<|,L,R));
}
void change(int x,int val){
x=pl[x];t[x].Min=val;x>>=;
while(x){
t[x].Min=min(t[x<<].Min,t[x<<|].Min);
x>>=;
}
}
int get(int x,int y){
int Min=;
while(up[x]!=up[y]){
if(deep[up[x]]<deep[up[y]])swap(x,y);
Min=min(Min,query(,dfn[up[x]],dfn[x]));
x=fa[up[x]];
}
if(deep[x]<deep[y])swap(x,y);
Min=min(Min,query(,dfn[y],dfn[x]));
if(y>NN)Min=min(Min,w[fa[y]]);
return Min;
}
int main(){
n=NN=read();m=read();int q=read();
for(rt i=;i<=n;i++)w[i]=read();
for(rt i=;i<=m;i++){
x=read();y=read();
add(x,y);
add(y,x);
}
tarjan();cnt=;
dfs(,);dfs2(,);build(,,n);
while(q--){
char c=getopt();x=read();y=read();
if(c=='C'){
if(x!=){
s[fa[x]].erase(s[fa[x]].find(w[x]));
s[fa[x]].insert(y);
int v=*s[fa[x]].begin();
if(v!=w[fa[x]]){
w[fa[x]]=v;
change(fa[x],v);
}
}
w[x]=y;
change(x,y);
continue;
}
writeln(get(x,y));
}
return ;
}
UOJ #30【CF Round #278】Tourists的更多相关文章
- UOJ #30. 【CF Round #278】Tourists
Description Cyberland 有 n 座城市,编号从 1 到 n,有 m 条双向道路连接这些城市.第 j 条路连接城市 aj 和 bj.每天,都有成千上万的游客来到 Cyberland ...
- UOJ30——【CF Round #278】Tourists
1.感谢taorunz老师 2.题目大意:就是给个带权无向图,然后有两种操作, 1是修改某个点的权值 2是询问,询问一个值,就是u到v之间经过点权的最小值(不可以经过重复的点) 操作数,点数,边数都不 ...
- 【题解】【CF Round #278】Tourists
圆方树第二题…… 图中询问的是指定两点之间简单路径上点的最小权值.若我们建出圆方树,圆点的权值为自身权值,方点的权值为所连接的圆点的权值最小值(即点双连通分量中的最小权值).我们可以发现其实就是这两点 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- UOJ #30. [CF Round #278] Tourists
UOJ #30. [CF Round #278] Tourists 题目大意 : 有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种 ...
- UOJ 275. 【清华集训2016】组合数问题
UOJ 275. [清华集训2016]组合数问题 组合数 $C_n^m $表示的是从 \(n\) 个物品中选出 \(m\) 个物品的方案数.举个例子,从$ (1,2,3)(1,2,3)$ 三个物品中选 ...
- UOJ #269. 【清华集训2016】如何优雅地求和
UOJ #269. [清华集训2016]如何优雅地求和 题目链接 给定一个\(m\)次多项式\(f(x)\)的\(m+1\)个点值:\(f(0)\)到\(f(m)\). 然后求: \[ Q(f,n,x ...
- UOJ #449. 【集训队作业2018】喂鸽子
UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...
- [UOJ#276]【清华集训2016】汽水
[UOJ#276][清华集训2016]汽水 试题描述 牛牛来到了一个盛产汽水的国度旅行. 这个国度的地图上有 \(n\) 个城市,这些城市之间用 \(n−1\) 条道路连接,任意两个城市之间,都存在一 ...
随机推荐
- (转)Java动态追踪技术探究
背景:美团的技术沙龙分享的文章都还是很不错的,通俗易懂,开阔视野,后面又机会要好好实践一番. Java动态追踪技术探究 楔子 jsp的修改 重新加载不需要重启servlet.如何在不重启jvm的情况下 ...
- python之路入门篇
一. Python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,Guido开始写能够解释Python语言语法的解释器.Python这个名字,来 ...
- (分治法 快速幂)P1226 【模板】快速幂||取余运算 洛谷
题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整数b,p,k. 输出格式: 输出“b^p mod k=s” s为运算结果 输入输 ...
- consul配置和使用
一:consul介绍 consul用于提供服务发现和服务配置的工具.有以下特性:1. 服务发现 consul的客户端提供一个服务,比如api或者mysql,另外一个客户端就可以去发现指定服务的服务提供 ...
- MySQL利用binlog恢复误操作数据(python脚本)
在人工手动进行一些数据库写操作的时候(比方说数据订正),尤其是一些不可控的批量更新或删除,通常都建议备份后操作.不过不怕万一,就怕一万,有备无患总是好的.在线上或者测试环境误操作导致数据被删除或者更新 ...
- urllib 学习一
说明:Urllib 是一个python用于操作URL的模块 python2.x ----> Urillib/Urllib2 python3.x ----> Urllib ...
- oracle里实例和数据库之间的关系
一个数据库服务器上可以装几个数据库它们都是用sid来标志,例如orcl1,orcl2,orcl3等等,一个数据库如orcl1中可以有多个实例吗? Oracle数据库,实际上应该是说,我们使用的是Ora ...
- python遇到的知识点
python遇到的知识点,记录一下.方便学习. 文件相关操作 查了资料,关于open()的mode参数: 'r':读 'w':写 'a':追加 'r+' == r+w(可读可写,文件若不存在就报错(I ...
- Centos6.6搭建Maven私服
操作系统:Centos6.6 私服Ip:10.0.210.112 JDK:1.7 (已安装并配置好了环境变量) 1:上 传 nexus-2.11.2-03-bundle.tar.gz到/root/ne ...
- Entity Framework Code First 学习日记(1)精
我最近几天正在学习Entity Framework Code First.我打算分享一系列的学习笔记,今天是第一部分: 为什么要使用Code First: 近 年来,随着domain driven d ...