圆方树的问题。
调了挺久的。
先把圆方树给建出来,然后考虑怎么求答案。
那么一个方点代表一个点双,那自然是这个点双里的答案。
考虑改变一个点时,把这个的点的父亲方点的平衡树里更改。
这样保证复杂度。
于是乎套上树剖,注意当两点\(lca\)为方点时,答案还要考虑该方点的父亲圆点。
开始码,妥妥的码农题(也可能是我菜,码了\(200h\)
CF487E Tourists
#include<iostream>
#include<cstdio>
#include<set>
#include<cstring>
#include<stack>
#define ll long long
#define N 400000
struct P{
int to,next;
};
struct Map{
P e[N];
int cnt,head[N];
Map(){
cnt = 0;
std::memset(head,0,sizeof(head));
}
inline void add(int x,int y){
// std::cout<<x<<" "<<y<<std::endl;
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
}A,T;
ll n,m,Q,w[N];
ll dfncnt,dfn[N],low[N],fcnt;
bool vis[N];
std::stack<int>QWQ;
inline void tarjan(int u){
dfn[u] = low[u] = ++dfncnt;
QWQ.push(u);
for(int i = A.head[u];i;i = A.e[i].next){
int v = A.e[i].to;
if(!dfn[v]){
tarjan(v);
low[u] = std::min(low[u],low[v]);
if(low[v] == dfn[u]){
++fcnt;
while(QWQ.top() != v){
T.add(fcnt,QWQ.top());
T.add(QWQ.top(),fcnt);
QWQ.pop();
}
T.add(fcnt,QWQ.top());
T.add(QWQ.top(),fcnt);
QWQ.pop();
T.add(fcnt,u);
T.add(u,fcnt);
}
}
else
low[u] = std::min(low[u],dfn[v]);
}
}
ll dep[N],siz[N],son[N],top[N],to[N],f[N];
inline void dfs(int u,int fa){
f[u] = fa,siz[u] = 0,dep[u] = dep[fa] + 1;
for(int i = T.head[u];i;i = T.e[i].next){
int v = T.e[i].to;
if(v == fa)
continue;
dfs(v,u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])
son[u] = v;
}
}
inline void dfs2(int u,int f,int tp){
dfn[u] = ++dfncnt,to[dfn[u]] = u,top[u] = tp;
if(son[u])
dfs2(son[u],u,tp);
for(int i = T.head[u];i;i = T.e[i].next){
int v = T.e[i].to;
if(v == son[u] || v == f)
continue;
dfs2(v,u,v);
}
}
ll t[N << 2];
#define mid ((l + r) >> 1)
#define li (now << 1)
#define ri ((now << 1) | 1)
inline void build(int now,int l,int r){
if(l == r){
t[now] = w[to[l]];
// std::cout<<now<<" "<<l<<" "<<r<<" "<<t[now]<<std::endl;
return;
}
build(li,l,mid);
build(ri,mid + 1,r);
t[now] = std::min(t[li],t[ri]);
// std::cout<<now<<" "<<l<<" "<<r<<" "<<t[now]<<std::endl;
}
inline void mdf(int now,int l,int r,int p,int x){
if(l == r){
t[now] = x;
return;
}
if(p <= mid)
mdf(li,l,mid,p,x);
else
mdf(ri,mid + 1,r,p,x);
t[now] = std::min(t[li],t[ri]);
}
inline ll q(int now,int l,int r,int tl,int tr){
// std::cout<<now<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<t[now]<<std::endl;
if(tl <= l && r <= tr)
return t[now];
ll ans = 0x3f3f3f3f;
if(tl <= mid)
ans = std::min(ans,q(li,l,mid,tl,tr));
if(tr > mid)
ans = std::min(ans,q(ri,mid + 1,r,tl,tr));
return ans;
}
std::multiset<int> s[N * 2];
int main(){
scanf("%lld%lld%lld",&n,&m,&Q);
fcnt = n;
for(int i = 1;i <= n;++i)
scanf("%lld",&w[i]);
for(int i = 1;i <= m;++i){
int x,y;
scanf("%d%d",&x,&y);
A.add(x,y);
A.add(y,x);
}
for(int i = 1;i <= n;++i){
if(!dfn[i])
tarjan(i);
}
dfncnt = 0;
dfs(1,0);
dfs2(1,0,1);
for(int i = 1;i <= n;++i)
if(f[i])
s[f[i]].insert(w[i]);
for(int i = n + 1;i <= dfncnt;++i)
w[i] = *s[i].begin();
build(1,1,dfncnt);
std::cout<<q(1,1,dfncnt,7,7)<<std::endl;
while(Q -- ){
char a[3];
int x,y;
scanf("%s%d%d",a,&x,&y);
if(a[0] == 'C'){
if(f[x]){
s[f[x]].insert(y);
s[f[x]].erase(s[f[x]].lower_bound(w[x]));
if(w[f[x]] != *s[f[x]].begin()){
w[f[x]] = *s[f[x]].begin();
mdf(1,1,dfncnt,dfn[f[x]],w[f[x]]);
}
}
w[x] = y;
}
if(a[0] == 'A'){
ll ans = 0x3f3f3f3f;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])
std::swap(x,y);
ans = std::min(ans,q(1,1,dfncnt,dfn[top[x]],dfn[x]));
x = f[top[x]];
}
// std::cout<<ans<<std::endl;
if(dfn[x] > dfn[y])
std::swap(x,y);
ans = std::min(ans,q(1,1,dfncnt,dfn[x],dfn[y]));
// std::cout<<ans<<std::endl;
if(x > n)
ans = std::min(ans,w[f[x]]);
std::cout<<ans<<std::endl;
}
}
}