传送门

先把边双连通分量用圆方树一样的方法缩点,然后把新建的树树剖维护。

注意对于边双连通分量需要维护动态最小值,可以用multisetmultisetmultiset。

代码:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=2e5+5,M=3e5+5;
int siz[N],w[N<<1],top[N],dep[N],pred[N],hson[N],num[N],dfn[N],low[N],tot=0,sig=0,n,m,q,blo[N],stk[N],Top=0,fa[N];
struct Node{int l,r,mn;}T[N<<2];
vector<int>g[N],e[N<<1];
multiset<int>W[N<<1];
inline void tarjan(int p,int pre){
	dfn[p]=low[p]=++tot,stk[++Top]=p;
	for(int i=0;i<g[p].size();++i){
		int v=g[p][i];
		if(v==pre)continue;
		if(!dfn[v]){
			tarjan(v,p),low[p]=min(low[p],low[v]);
			if(low[v]>=dfn[p]){
				int tmp;
				++sig,e[p].push_back(sig);
				do tmp=stk[Top--],blo[tmp]=sig,e[sig].push_back(tmp),W[sig].insert(w[tmp]);while(tmp^v);
				w[sig]=*(W[sig].begin());
			}
		}
		else low[p]=min(low[p],dfn[v]);
	}
}
inline void dfs1(int p){
	siz[p]=1;
	for(int i=0;i<e[p].size();++i){
		int v=e[p][i];
		if(v==fa[p])continue;
		fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
		if(siz[v]>siz[hson[p]])hson[p]=v;
	}
}
inline void dfs2(int p,int tp){
	top[p]=tp,pred[num[p]=++tot]=p;
	if(!hson[p])return;
	dfs2(hson[p],tp);
	for(int i=0;i<e[p].size();++i){
		int v=e[p][i];
		if(v!=fa[p]&&v!=hson[p])dfs2(v,v);
	}
}
inline void pushup(int p){T[p].mn=min(T[lc].mn,T[rc].mn);}
inline void build(int p,int l,int r){
	T[p].l=l,T[p].r=r;
	if(l==r){T[p].mn=w[pred[l]];return;}
	build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int k,int v){
	if(T[p].l==T[p].r){T[p].mn=v;return;}
	if(k<=mid)update(lc,k,v);
	else update(rc,k,v);
	pushup(p);
}
inline int query(int p,int ql,int qr){
	if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn;
	if(qr<=mid)return query(lc,ql,qr);
	if(ql>mid)return query(rc,ql,qr);
	return min(query(lc,ql,mid),query(rc,mid+1,qr));
}
inline int ask(int x,int y){
	int ret=1e9;
	while(top[x]^top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		ret=min(ret,query(1,num[top[x]],num[x])),x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	ret=min(query(1,num[y],num[x]),ret);
	if(y>n&&fa[y])ret=min(ret,w[fa[y]]);
	return ret;
}
inline void modify(int p,int v){
	if(blo[p]){
		set<int>::iterator it=W[blo[p]].find(w[p]);
		W[blo[p]].erase(it),W[blo[p]].insert(v),w[blo[p]]=*(W[blo[p]].begin()),update(1,num[blo[p]],w[blo[p]]);
	}
	w[p]=v,update(1,num[p],v);
}
int main(){
	sig=n=read(),m=read(),q=read();
	for(int i=1;i<=n;++i)w[i]=read();
	for(int i=1,u,v;i<=m;++i)u=read(),v=read(),g[u].push_back(v),g[v].push_back(u);
	tarjan(1,0),dfs1(1),tot=0,dfs2(1,1),build(1,1,sig);
	for(int i=1,x,y;i<=q;++i){
		char s[5];
		scanf("%s",s),x=read(),y=read();
		if(s[0]=='C')modify(x,y);
		else printf("%d\n",ask(x,y));
	}
}

2018.11.09 codeforces487E. Tourists(tarjan+树链剖分)的更多相关文章

  1. JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分

    http://172.20.6.3/Problem_Show.asp?id=1454 从这道题我充分认识到我的脑子里好多水orz. 如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一 ...

  2. 2018.10.12 bzoj4712: 洪水(树链剖分)

    传送门 树链剖分好题. 考虑分开维护重儿子和轻儿子的信息. 令f[i]f[i]f[i]表示iii为根子树的最优值,h[i]h[i]h[i]表示iii重儿子的最优值,g[i]g[i]g[i]表示iii所 ...

  3. 【BZOJ4568】幸运数字(线性基,树链剖分,ST表)

    [BZOJ4568]幸运数字(线性基,树链剖分,ST表) 题面 BZOJ Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市 ...

  4. 【BZOJ1036】树的统计Count(树链剖分,LCT)

    题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: ...

  5. 2018.09.16 bzoj3626: [LNOI2014]LCA(树链剖分)

    传送门 树链剖分好题. 对于每个点维护一个值vi" role="presentation" style="position: relative;"&g ...

  6. 2018.08.09 bzoj4719: [Noip2016]天天爱跑步(树链剖分)

    传送门 话说开始上文化课之后写题时间好少啊. 这道题将一个人的跑步路线拆成s->lca,lca->t,然后对于第一段上坡路径要经过的点,当前这个人能对它产生贡献当且仅当dep[s]-dep ...

  7. BZOJ_4326_[NOIP2015]_运输计划_(二分+LCA_树链剖分/Tarjan+差分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4326 给出一棵带有边权的树,以及一系列任务,任务是从树上的u点走到v点,代价为u到v路径上的权 ...

  8. 2018.06.29 洛谷P1505 [国家集训队]旅游(树链剖分)

    旅游 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有 ...

  9. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

随机推荐

  1. js改变表单的内容样式

    一.改变单个样式    var obj = document.getElementById("id");   obj.style.cssText = " display: ...

  2. jasper打印实例2 ----通过文件字节流获得PDF格式图片

    public class IspReportUtil { public static String exportReportToByte(CommonReportHandler handler)thr ...

  3. RxJS之BehaviorSubject

    Subject 的其中一个变体就是 BehaviorSubject,它有一个“当前值”的概念.它保存了发送给消费者的最新值.并且当有新的观察者订阅时,会立即从 BehaviorSubject 那接收到 ...

  4. git add和git commit

    git命令使用:提交前可指定要提交哪些文件,然后使用git commit来提交 样例: git status 输出: Changes to be committed: modified:   app/ ...

  5. java 空格替换%20

    public String replaceSpace(StringBuffer str2) { StringBuffer str4 = new StringBuffer(); int length=s ...

  6. Incorrect Invoice Ref.

    IF_EX_ACC_DOCUMENT~CHANGE LOOP AT c_accit ASSIGNING <wa_accit> WHERE rebzg eq 'V'. <wa_acci ...

  7. Nginx+Tomcat 实现动态分离,负载均衡

    什么是动静分离 为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源比如图片,js,css等文件,我们可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时 ...

  8. c#tcp源端口号和目的端口怎么理解

    在一台机器上,一个进程对应一个端口.端口的作用就是用来唯一标识这个进程.源端口标识发起通信的那个进程,目的端口标识接受通信的那个进程.有了端口号,接受到报文后才能够知道将报文发送到哪个进程.

  9. numpy常见属性、创建数组

      1.几种常见numpy的属性 ndim:维度 shape:行数和列数 size:元素个数 >>> import numpy as np #导入numpy模块,np是为了使用方便的 ...

  10. NC 6系后台调用接口保存单据

    IPFBusiAction ipf = (IPFBusiAction)NCLocator.getInstance().lookup(IPFBusiAction.class); ipf.processA ...