先把边双连通分量用圆方树一样的方法缩点,然后把新建的树树剖维护。
注意对于边双连通分量需要维护动态最小值,可以用
multisetmultisetmultiset。
代码:
#include #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 g[N],e[N<<1];multiset W[N<<1];inline void tarjan(int p,int pre){ dfn[p]=low[p]=++tot,stk[++Top]=p; for(int i=0;i =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 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 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]] n&&fa[y])ret=min(ret,w[fa[y]]); return ret;}inline void modify(int p,int v){ if(blo[p]){ set ::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)); }}