CF487E Tourists 圆方树、树链剖分
注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点
注意:这里不能缩边双联通分量,样例\(2\)就是一个反例
上面这个图如果缩点双会缩成\(3\)个,但是缩边双会将整个图缩成\(1\)个点。
假如我们询问的是\((1,4)\)之间的简单路径,而图中权值最小的点为\(7\)号点,那么如果缩成了边双联通分量,你的答案会是\(7\)号点的权值,意即认为可以走到\(7\)号点,但实际上如果到\(7\)号点,意味着\(5\)号点需要经过\(2\)次,不符合简单路径的要求
所以如果将题意改成“一条边只能经过一次”就是缩边双了
那么我们直接维护圆方树,对于每一个方点使用\(multiset\)维护与它相连的所有圆点的权值,在圆方树上树链剖分计算答案。
当然这样子还是不够的。考虑一种情况:一个圆点连接了一堆方点,然后在这一个圆点上不断进行修改操作,这样每一次修改都会波及一大堆方点的修改,复杂度直接爆炸。
优化:对于所有方点,不去维护它在圆方树上的父亲,那么对于每一次修改,只会波及它在圆方树上的方点父亲。而如果在某一次询问中两点之间的\(LCA\)为方点,还需要额外考虑这个点的父亲的贡献。
#include<bits/stdc++.h>
#define lch (x << 1)
#define rch (x << 1 | 1)
#define mid ((l + r) >> 1)
#define INF 0x7fffffff
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 2e5 + 7;
struct Edge{
int end , upEd;
}Ed[MAXN << 1];
int head[MAXN] , val[MAXN] , N , M , Q , cntEd , cnt;
int topS , ts , st[MAXN] , dfn[MAXN] , low[MAXN];
int ind[MAXN] , rk[MAXN] , fa[MAXN] , dep[MAXN] , son[MAXN] , sz[MAXN] , top[MAXN] , TS;
int Tree[MAXN << 2];
bool vis[MAXN];
vector < int > ch[MAXN];
multiset < int > s[MAXN];
inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
}
inline void pop(int t , int bot){
ch[t].push_back(++cnt);
do{
ch[cnt].push_back(st[topS]);
s[cnt].insert(val[st[topS]]);
}while(st[topS--] != bot);
}
void tarjan(int x , int p){
st[++topS] = x;
dfn[x] = low[x] = ++ts;
vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(Ed[i].end != p)
if(!vis[Ed[i].end]){
tarjan(Ed[i].end , x);
low[x] = min(low[x] , low[Ed[i].end]);
if(low[Ed[i].end] >= dfn[x])
pop(x , Ed[i].end);
}
else
low[x] = min(low[x] , dfn[Ed[i].end]);
}
void dfs1(int x , int p){
fa[x] = p;
dep[x] = dep[p] + 1;
sz[x] = 1;
for(int i = 0 ; i < ch[x].size() ; ++i){
dfs1(ch[x][i] , x);
sz[x] += sz[ch[x][i]];
if(sz[son[x]] < sz[ch[x][i]])
son[x] = ch[x][i];
}
}
void dfs2(int x , int t){
ind[x] = ++TS;
rk[TS] = x;
top[x] = t;
if(!son[x])
return;
dfs2(son[x] , t);
for(int i = 0 ; i < ch[x].size() ; ++i)
if(ch[x][i] != son[x])
dfs2(ch[x][i] , ch[x][i]);
}
inline void pushup(int x){
Tree[x] = min(Tree[lch] , Tree[rch]);
}
void init(int x , int l , int r){
if(l == r)
Tree[x] = rk[l] <= N ? val[rk[l]] : *s[rk[l]].begin();
else{
init(lch , l , mid);
init(rch , mid + 1 , r);
pushup(x);
}
}
void modify(int x , int l , int r , int tar , int num){
if(l == r)
Tree[x] = num;
else{
if(mid >= tar)
modify(lch , l , mid , tar , num);
else
modify(rch , mid + 1 , r , tar , num);
pushup(x);
}
}
int query(int x , int l , int r , int L , int R){
if(l >= L && r <= R)
return Tree[x];
int minN = INF;
if(mid >= L)
minN = min(minN , query(lch , l , mid , L , R));
if(mid < R)
minN = min(minN , query(rch , mid + 1 , r , L , R));
return minN;
}
int work(int x , int y){
int tx = top[x] , ty = top[y] , minN = INF;
while(tx != ty){
if(dep[tx] < dep[ty]){
swap(x , y);
swap(tx , ty);
}
minN = min(minN , query(1 , 1 , cnt , ind[tx] , ind[x]));
x = fa[tx];
tx = top[x];
}
if(dep[x] > dep[y])
swap(x , y);
minN = min(minN , query(1 , 1 , cnt , ind[x] , ind[y]));
if(x > N)
minN = min(minN , val[fa[x]]);
return minN;
}
inline char getc(){
char c = getchar();
while(!isupper(c))
c = getchar();
return c;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
cnt = N = read();
M = read();
Q = read();
for(int i = 1 ; i <= N ; ++i)
val[i] = read();
for(int i = 1 ; i <= M ; ++i){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
tarjan(1 , 0);
dfs1(1 , 0);
dfs2(1 , 1);
init(1 , 1 , cnt);
while(Q--)
if(getc() == 'A')
printf("%d\n" , work(read() , read()));
else{
int a = read() , b = read();
if(a != 1){
s[fa[a]].erase(s[fa[a]].find(val[a]));
s[fa[a]].insert(b);
modify(1 , 1 , cnt , ind[fa[a]] , *s[fa[a]].begin());
}
val[a] = b;
modify(1 , 1 , cnt , ind[a] , b);
}
return 0;
}
CF487E Tourists 圆方树、树链剖分的更多相关文章
- CF487E Tourists(圆方树+树链剖分+multiset/可删堆)
CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...
- CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...
- CF487E Tourists[圆方树+树剖(线段树套set)]
做这题的时候有点怂..基本已经想到正解了..结果感觉做法有点假,还是看了正解题解.. 首先提到简单路径上经过的点,就想到了一个关于点双的结论:两点间简单路径上所有可能经过的点的并等于路径上所有点所在点 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- Tourists——圆方树
CF487E Tourists 一般图,带修求所有简单路径代价. 简单路径,不能经过同一个点两次,那么每个V-DCC出去就不能再回来了. 所以可以圆方树,然后方点维护一下V-DCC内的最小值. 那么, ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- CF487E Tourists - Tarjan缩点 + 树剖 + multiset
Solution 先Tarjan求出点双联通分量 并缩点. 用$multiset$维护 点双内的最小点权. 容易发现, 点双内的最小点权必须包括与它相连的割边的点权. 所以我们必须想办法来维护. 所以 ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- CF487E Tourists 【圆方树 + 树剖 + 堆】
题目链接 CF487E 题解 圆方树 + 树剖 裸题 建好圆方树维护路径上最小值即可 方点的值为其儿子的最小值,这个用堆维护 为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆 这样充分利用 ...
随机推荐
- Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题
最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候 出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就 ...
- 开始记录 Windows Phone 生涯
已经快接近三年没有更新博客了,最近打算把博客这块从新建设起来. 由于工作原因,现在已经很久没有接触过Android了.目前工作是全力 Windows Phone,并且也已经工作一年半了,以后会陆续把之 ...
- Python笔记(十四):操作excel openpyxl模块
(一) 常遇到的情况 就我自己来说,常遇到的情况可能就下面几种: 读取excel整个sheet页的数据. 读取指定行.列的数据 往一个空白的excel文档写数据 往一个已经有数据的excel文档追加 ...
- 结对项目-四则运算"软件"之升级版
本次作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2213 github地址为:https://github.com/L ...
- Android、IOS文字居中偏离的解决方案
前言 移动端开发,经常会遇到的问题,就是文字居中.一般都只能往css方向去fix这个问题. 自己以前也用过position:relative;top:-*px的方式去解决.
- [Linux.NET]Nginx 泛解析配置请求映射到多端口实现二级域名访问
由于想实现一个域名放置多个应用运行的目的,而不想通过域名后加端口号方式处理,这种方式处理记起来太麻烦,偷懒党简直不能忍,故而考虑了使用二级域名来处理多个应用同时运行.Google了一番资料并进行了尝试 ...
- Spring Data JPA方法定义规范
Spring Data Jpa方法定义的规则: (1)简单条件查询 简单条件查询:查询某一个实体类或者集合. 按照Spring Data的规范的规定,查询方法以find | read | get开头, ...
- VMware导入OVF时报错(未能部署OVF包用户取消了任务的解决办法)
阅读目录: 1.问题 2.原因 3.解决方案 问题:部署OVF模版的时候报错“用户取消了任务” 原因:导出ovf模板时,虚拟CD-ROM的选项要选[客户端设备],否则导入时报错“用户取消了任务” 解决 ...
- Linq2DB之研究和探索
1,对linq2db使用看法 最近在研究linq2db,用起来还不错,性能还不错的.之前也在博客园有些网友说用ado.net和depper写SQL语句,性能还要高.有时候牺牲点性能,为了提高开发效率, ...
- asp在线压缩和解压缩文件(文件夹)
<%'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\\'\\ 1. c:\windows\system32\cmd.e ...