傳送門
先把邊雙連通分量用圓方樹一樣的方法縮點,然后把新建的樹樹剖維護。
注意對于邊雙連通分量需要維護動態最小值,可以用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
));}
}
轉載于:https://www.cnblogs.com/ldxcaicai/p/10084729.html
總結
以上是生活随笔為你收集整理的2018.11.09 codeforces487E. Tourists(tarjan+树链剖分)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。