题意:一个无向连通图,点有点权,支持单点修改和查询,查询$(x,y)$是找出一条$x$到$y$的简单路径使得路径点权最小值最小,输出这个最小值

码农题...而且细节很多...

先找边双连通分量缩点,对于每个边双,新建一个节点和边双中的每个点连边,不属于任何边双的边就直接连,这样可以建出一棵树,然后就变成树上的问题了,因为进入一个边双就可以遍历它的所有点

对于新建的点,开一个multiset存它儿子的权值,它自己的权值设为multiset的最小值

查询就是路径$\min$,注意如果lca是新建点,那么这个lca的父亲的权值也应该被统计

修改就修改单点,如果父亲是新建点就更新它的multiset还有权值

注意在tarjan时栈中保存的应该是边而不是点

#include<stdio.h>
#include<vector>
#include<set>
using namespace std;
const int inf=2147483647;
int v[100010],n,m,q,C;
struct tree{int h[200010],nex[400010],to[400010],M;multiset<int>s[200010];void ins(int a,int b){M++;to[M]=b;nex[M]=h[a];h[a]=M;}void add(int a,int b){ins(a,b);ins(b,a);}int fa[200010][18],dep[200010];void dfs(int x){dep[x]=dep[fa[x][0]]+1;for(int i=h[x];i;i=nex[i]){if(to[i]!=fa[x][0]){if(x>n)s[x].insert(v[to[i]]);fa[to[i]][0]=x;dfs(to[i]);}}if(x>n)v[x]=*s[x].begin();}int lca(int x,int y){int i;if(dep[x]<dep[y])swap(x,y);for(i=17;i>=0;i--){if(dep[fa[x][i]]>=dep[y])x=fa[x][i];}if(x==y)return x;for(i=17;i>=0;i--){if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}}return fa[x][0];}int siz[200010],son[200010],pos[200010],bl[200010];void dfs1(int x){int i,k=0;siz[x]=1;for(i=h[x];i;i=nex[i]){if(to[i]!=fa[x][0]){dfs1(to[i]);siz[x]+=siz[to[i]];if(siz[to[i]]>siz[k])k=to[i];}}son[x]=k;}void dfs2(int x,int chain){pos[x]=++M;bl[x]=chain;if(son[x])dfs2(son[x],chain);for(int i=h[x];i;i=nex[i]){if(to[i]!=fa[x][0]&&to[i]!=son[x])dfs2(to[i],to[i]);}}int T[800010];void modify(int x,int v){T[x+=M]=v;for(x>>=1;x;x>>=1)T[x]=min(T[x<<1],T[x<<1|1]);}int query(int s,int t){int res=inf;for(s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1){if(~s&1)res=min(res,T[s^1]);if(t&1)res=min(res,T[t^1]);}return res;}void gao(){int i,j;dfs(1);for(j=1;j<18;j++){for(i=1;i<=C;i++)fa[i][j]=fa[fa[i][j-1]][j-1];}dfs1(1);M=0;dfs2(1,1);for(M=1;M<=C+1;M<<=1);for(i=0;i<M;i++)T[i+M]=inf;for(i=1;i<=C;i++)T[pos[i]+M]=v[i];for(i=M-1;i>0;i--)T[i]=min(T[i<<1],T[i<<1|1]);}int querych(int x,int y){int res=inf;while(bl[x]!=bl[y]){if(dep[bl[x]]<dep[bl[y]])swap(x,y);res=min(res,query(pos[bl[x]],pos[x]));x=fa[bl[x]][0];}if(pos[x]>pos[y])swap(x,y);res=min(res,query(pos[x],pos[y]));if(x>n)res=min(res,v[fa[x][0]]);return res;}void modifypt(int x,int d){if(fa[x][0]&&fa[x][0]>n){s[fa[x][0]].erase(s[fa[x][0]].find(v[x]));s[fa[x][0]].insert(d);modify(pos[fa[x][0]],*s[fa[x][0]].begin());}v[x]=d;modify(pos[x],d);}
}tr;
struct graph{int h[100010],nex[200010],to[200010],M;graph(){M=1;}int fix(int i){return i&1?i^1:i;}void add(int a,int b){M++;to[M]=b;nex[M]=h[a];h[a]=M;}int dfn[100010],low[100010],stk[100010],vis[100010],tp,K;bool ins[200010];vector<int>V;void dfs(int x){int i,j,t,n,m;dfn[x]=low[x]=++M;for(i=h[x];i;i=nex[i]){if(!dfn[to[i]]){ins[stk[++tp]=fix(i)]=1;dfs(to[i]);low[x]=min(low[x],low[to[i]]);if(low[to[i]]>=dfn[x]){K++;V.clear();j=tp;m=0;do{t=stk[j--];m++;if(vis[to[t]]!=K){vis[to[t]]=K;V.push_back(to[t]);}if(vis[to[t^1]]!=K){vis[to[t^1]]=K;V.push_back(to[t^1]);}}while(t!=fix(i));n=V.size();if(m<n)tr.add(x,to[i]);else{C++;for(int x:V)tr.add(x,C);}do{ins[t=stk[tp--]]=0;}while(t!=fix(i));}}else{low[x]=min(low[x],dfn[to[i]]);if(!ins[fix(i)]&&dfn[to[i]]<dfn[x])ins[stk[++tp]=fix(i)]=1;}}}void gao(){int i,x,y;for(i=1;i<=n;i++)scanf("%d",v+i);for(i=1;i<=m;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}M=0;C=n;dfs(1);}
}g;
int main(){char s[5];int x,y;scanf("%d%d%d",&n,&m,&q);g.gao();tr.gao();while(q--){scanf("%s%d%d",s,&x,&y);if(s[0]=='C')tr.modifypt(x,y);elseprintf("%d\n",tr.querych(x,y));}
}

转载于:https://www.cnblogs.com/jefflyy/p/9480473.html

[CF487E]Tourists相关推荐

  1. 【学习笔记】圆方树(CF487E Tourists)

    终于学了圆方树啦~\(≧▽≦)/~ 感谢y_immortal学长的博客和帮助 把他的博客挂在这里~ 点我传送到巨佬的博客QwQ! 首先我们来介绍一下圆方树能干什么呢qwq 1.将图上问题简化到树上问题 ...

  2. CF487E Tourists(圆方树+树链剖分)

    洛谷题目传送门 解题思路 不会圆方树的可以看我的博客圆方树学习记录及例题 首先Tarjan寻找点双连通分量,然后建立圆方树,每个方点存这个点双内的最小点权 将圆方树树链剖分之后,对于修改操作,将这个点 ...

  3. ZJOI2019一轮停课刷题记录

    Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...

  4. 每周记录(4月底停更了qvq)

    1月6日 旋转卡壳 闵可夫斯基和 1月13日 期末复习 1月20日 网络流前4道题 一场失败的期末考试 写寒假作业 bzoj [HNOI2008]明明的烦恼(90分) prufer序列 正睿 画画图 ...

  5. 圆方树学习记录及例题

    对于一个无向连通图,我们可以通过一些操作使其变成一棵树,然后再在树上操作 这颗树就叫圆方树,具体是怎么样的呢?看下图 这是一个无向连通图 然后找到每一个点双连通分量,并在这个点双里新建一个节点,并且是 ...

  6. 【蒟蒻の笔记】圆方树初识

    圆方树 首先描述一下圆方树: 注:我们把一条边连接两个节点的图也认为是点双连通的. 对于一个无向连通图,对于每个点双连通分量建立一个新的点,新的点作为"方点",原本的点作为&quo ...

  7. 【CF487E】Tourists【圆方树】【树链剖分】【multiset】

    题意:给一张 nnn 点 mmm 边的连通无向图,点帯权,qqq 次操作: 修改一个点的权值. 询问两点间所有简单路的最小权值的最小值. n,m,q≤105n,m,q\leq 10^5n,m,q≤10 ...

  8. 每日英语:Foreign Tourists Skip Beijing

    Overseas tourists continued to shun Beijing through 2013. shun:避开,避免,回避 Amid rising pollution and a ...

  9. 广义圆方树+树链剖分+set(Codeforces Round #278 (Div. 1): E. Tourists)

    前置:双联通分量.圆方树.树链剖分 什是是广义圆方树 圆方树是针对于仙人掌建树,而广义圆方树是针对无向图建树,对于一个无向图 无向图中的所有点 → 广义圆方树中的所有圆点 无向图中的一个双联通分量 → ...

最新文章

  1. 学习笔记《Java多线程编程实战指南》四
  2. 经典面试题:为什么 ConcurrentHashMap 的读操作不需要加锁?
  3. 判断元素(expected_conditions)
  4. GlobalAlloc全局内存的使用
  5. 每次创建maven都要重新设置set,如何将本地maven设置为默认的maven
  6. android gpu 视频编码,android – 编码器崩溃对Adreno GPU编码从Surface
  7. 国内首款全国产固态硬盘控制芯片发布
  8. ilm 和dlm差异_《存储e周刊》第28期 信息生命周期管理之争
  9. 项目开发版本控制----Git
  10. centos 挂载与卸载硬盘
  11. ClickHouse:A股分钟数据的查询速度的测试[下]
  12. beanshell字符串替换_Beanshell语法
  13. 浏览器缓存机制:强缓存和协商缓存
  14. MATLAB求最大值max函数
  15. What’s difference between 1’s Complement and 2’s Complement?
  16. cp2102 vcp驱动
  17. NaN在js中的意义
  18. 完美世界手游服务器维护时间表,完美世界手游开服时间表 新区开服时间总览[多图]...
  19. UltraISO 软碟通制作系统U盘
  20. 【spring注解】spring注解入门

热门文章

  1. 进程用户态 上下文切换需要保存哪些_漫话性能:CPU上下文切换
  2. linux 内核升级 网络 不能上网,Deepin Linux 无法上网
  3. Clustering Coefficient
  4. AJAX框架衣柜内部结构,揭秘最实用的衣柜内部结构这样布局,速速get!
  5. python tkinter计算器实例_python小实例——tkinter实战(计算器)
  6. solidworks热分析_solidworks解决管道流体问题,原来可以如此轻松
  7. 基本数据结构篇(三万字总结)
  8. 笔记-项目整体管理-项目工作说明书
  9. Leaflet中使用leaflet-cion-pulse插件实现波动的图标效果
  10. JavaEE企业级快速开发平台jeesite4的使用和快速搭建项目