本题解并不提供圆方树讲解。

所以不会圆方树的出门右转问yyb

没有修改的话圆方树+链剖。

方点的权值为点双连通分量里的最小值。

然后修改的话圆点照修,每一个方点维护一个小根堆。

考虑到可能被菊花卡死。

我们每一个方点只维护儿子的最小值。

当询问的路径\(lca\)为方点时,\(ans=min(ans,w[fa[lca]])\)即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
#define ls now<<1
#define rs now<<1|1
const int N=444444;
struct queue{
priority_queue<int,vector<int>,greater<int> >q1;
priority_queue<int,vector<int>,greater<int> >q2;
void push(int x){q1.push(x);}
void del(int x){q2.push(x);}
int top(){
while(!q2.empty()&&q1.top()==q2.top())q1.pop(),q2.pop();
return q1.top();
}
}q[N];
struct Graph{
int cnt,head[N];
struct edge{
int to,nxt;
}e[N*2];
void add_edge(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
}g1,g2;
int dfn[N],low[N],tim,stack[N],Top,num;
void Tarjan(int u){
dfn[u]=low[u]=++tim;
stack[++Top]=u;
for(int i=g1.head[u];i;i=g1.e[i].nxt){
int v=g1.e[i].to;
if(dfn[v]==0){
Tarjan(v);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u]){
g2.add_edge(++num,u);
g2.add_edge(u,num);
int x;
do{
x=stack[Top--];
g2.add_edge(num,x);
g2.add_edge(x,num);
}while(x!=v);
}
}
else low[u]=min(low[u],dfn[v]);
}
}
int fa[N],size[N],dep[N],son[N];
int n,w[N];
void dfs1(int u,int f){
fa[u]=f;
size[u]=1;
dep[u]=dep[f]+1;
for(int i=g2.head[u];i;i=g2.e[i].nxt){
int v=g2.e[i].to;
if(v==f)continue;
if(u>n)q[u].push(w[v]);
dfs1(v,u);
size[u]+=size[v];
if(size[son[u]]<=size[v])son[u]=v;
}
}
int top[N],id[N],tot;
void dfs2(int u,int tp){
dfn[u]=++tot;
top[u]=tp;
id[tot]=u;
if(son[u])dfs2(son[u],tp);
for(int i=g2.head[u];i;i=g2.e[i].nxt){
int v=g2.e[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
int mn[N*4];
void update(int now){
mn[now]=min(mn[ls],mn[rs]);
}
void build(int l,int r,int now){
if(l==r){
if(id[l]<=n)mn[now]=w[id[l]];
else mn[now]=q[id[l]].top();
return;
}
int mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
update(now);
}
void change(int l,int r,int x,int c,int now){
if(l==r){
mn[now]=c;
return;
}
int mid=(l+r)>>1;
if(x>mid)change(mid+1,r,x,c,rs);
else change(l,mid,x,c,ls);
update(now);
}
int check(int l,int r,int L,int R,int now){
if(l==L&&r==R)return mn[now];
int mid=(l+r)>>1;
if(L>mid)return check(mid+1,r,L,R,rs);
else if(R<=mid)return check(l,mid,L,R,ls);
else return min(check(l,mid,L,mid,ls),check(mid+1,r,mid+1,R,rs));
}
int getlca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
if(dep[x]<dep[y])return x;
else return y;
}
int checkroad(int x,int y){
int mn=-1;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
if(mn==-1)mn=check(1,num,dfn[top[x]],dfn[x],1);
else mn=min(mn,check(1,num,dfn[top[x]],dfn[x],1));
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
if(mn==-1)mn=check(1,num,dfn[x],dfn[y],1);
else mn=min(mn,check(1,num,dfn[x],dfn[y],1));
return mn;
}
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int Q,m;
int main(){
n=read();m=read();Q=read();
num=n;
for(int i=1;i<=n;i++)w[i]=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
g1.add_edge(u,v);g1.add_edge(v,u);
}
Tarjan(1);
dfs1(1,0);
dfs2(1,1);
build(1,num,1);
char s[3];
while(Q--){
scanf("%s",s+1);
if(s[1]=='C'){
int x=read(),c=read();
if(dfn[x]!=1){
q[fa[x]].del(w[x]);
q[fa[x]].push(c);
change(1,num,dfn[fa[x]],q[fa[x]].top(),1);
}
w[x]=c;
change(1,num,dfn[x],c,1);
}
else{
int x=read(),y=read();
int lca=getlca(x,y);
int tmp=checkroad(x,y);
printf("%d\n",lca<=n?tmp:min(tmp,w[fa[lca]]));
}
}
return 0;
}

CF487E Tourists(圆方树+堆+链剖)的更多相关文章

  1. CF487E Tourists(圆方树+树链剖分+multiset/可删堆)

    CF487E Tourists(圆方树+树链剖分+multiset/可删堆) Luogu 给出一个带点权的无向图,两种操作: 1.修改某点点权. 2.询问x到y之间简单路径能走过的点的最小点权. 题解 ...

  2. CF487E Tourists 圆方树、树链剖分

    传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...

  3. CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)

    QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...

  4. CF487E Tourists[圆方树+树剖(线段树套set)]

    做这题的时候有点怂..基本已经想到正解了..结果感觉做法有点假,还是看了正解题解.. 首先提到简单路径上经过的点,就想到了一个关于点双的结论:两点间简单路径上所有可能经过的点的并等于路径上所有点所在点 ...

  5. uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)

    - 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...

  6. Tourists——圆方树

    CF487E Tourists 一般图,带修求所有简单路径代价. 简单路径,不能经过同一个点两次,那么每个V-DCC出去就不能再回来了. 所以可以圆方树,然后方点维护一下V-DCC内的最小值. 那么, ...

  7. CF487E Tourists 【圆方树 + 树剖 + 堆】

    题目链接 CF487E 题解 圆方树 + 树剖 裸题 建好圆方树维护路径上最小值即可 方点的值为其儿子的最小值,这个用堆维护 为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆 这样充分利用 ...

  8. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

  9. CF487E Tourists【圆方树+tarjan+multiset+树剖+线段树】

    圆方树不仅能解决仙人掌问题(虽然我仙人掌问题也没用过圆方树都是瞎搞过去的),还可以解决一般图的问题 一般图问题在于缩完环不是一棵树,所以就缩点双(包括双向边) 每个方点存他所在点双内除根以外的点的最小 ...

随机推荐

  1. 当li设置为line-block时,元素之间出现间隙的原因和解决方法

    原因 因为浏览器默认把inline元素之间的空白符(Tab.空格.换行)渲染成一个空格.而如下述代码,两个li元素之间的换行符被渲染成一个空格,则元素之间产生了间隙. 用Chrome浏览器将场景模拟出 ...

  2. C语言求大数的阶乘

    我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,该如何计算? 当一个数很大时,利用平常的方法是求不出来它的阶乘的,因为数据超出了范围.因此我们要用数组来求一个大数的阶乘,用数组的每位表示结果的 ...

  3. BA-siemens-apogee总线不稳定解决方法

    状况一:BLN下的火车头在线,但是下面的模块(包括UEC或者PPM)全部掉线 尝试方法: 使用挨个DDC箱断线的方法测试总线是否上线(可以解决由于总线短路引起的总线故障,施工中总线压冷压端子的话就不容 ...

  4. POJ 1320

    作弊了--!该题可以通过因式分解得到一个佩尔方程....要不是学着这章,估计想不到.. 得到x1,y1后,就直接代入递推式递推了 x[n]=x[n-1]*x[1]+d*y[n-1]*y[1] y[n] ...

  5. 剑指Offer面试题33(java版):把数组排成最小的数

    题目:输入一个正整数数组.把数组里面全部的数字拼接排成一个数,打印能拼接出的全部数字中的一个.比如输入数组{3,32.321}.则打印出这3个数字能排成的最小数字321323. 这个题目最直接的做法应 ...

  6. 《coredump问题原理探究》Linux x86版7.8节vector相关的iterator对象

    在前面看过了一个vectorcoredump的样例,接触了vector的iterator,能够知道vector的iterator仅仅有一个成员_M_current指向vector某一个元素. 先看一个 ...

  7. 巧用select延时

    在LINUX用户态的情况下.假设想要延时的话.用sleep是最合适的,可是,在有些情况下,须要更小单位的延时,ms  us 也是要的.用循环获取到的延时是不精确的. 幸好,select函数巧用的话,是 ...

  8. 2015.04.27,外语,读书笔记-《Word Power Made Easy》 12 “如何奉承朋友” SESSION 35

    1.how to look 拉丁词根specto,to look的意思,是许多常见英文词语的来源,如spectacle(['spektәkl] n. 值得看的东西, 光景, 眼镜).spectator ...

  9. [SCOI 2008] 奖励关

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1076 [算法] f[i][S]表示当前第i次抛出宝物,目前集合为S,所能获得的最高分 ...

  10. 杂项-Java:Spring

    ylbtech-杂项-Java:Spring Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring是于200 ...