思路是圆方树+树链剖分(线段树)+LCA。
另外,蒟蒻码力实在是太弱了,写稍微码量大一点的题就会寄QaQ。求大佬们提供码力提升题单,感激不尽!
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
struct stree
{
int l,r,val;
}t[800005];
struct edge
{
int v,nxt;
}e[200005],re[200005];
int n,m,u,v,q,pos,rpos,cnt,idx;
int a[200005],head[100005],rhead[200005],dfn[200005],low[200005];
int dep[200005],siz[200005],fa[200005],son[200005],/**/p[200005],top[200005];
int st[200005][21];
bool vis[200005];
char con;
stack<int>s;
multiset<int>ms[200005];
void addedge(int u,int v)
{
if(u==v)
return;
e[++pos]={v,head[u]};
head[u]=pos;
}
void raddedge(int u,int v)
{
if(u==v)
return;
re[++rpos]={v,rhead[u]};
rhead[u]=rpos;
}
//yuanfangtree
void tarjan(int u)
{
dfn[u]=low[u]=++idx;
s.push(u);
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]==dfn[u])
{
cnt++;
int lin=0;
while(s.size()&&lin!=v)
{
lin=s.top();
s.pop();
raddedge(lin,cnt);
raddedge(cnt,lin);
}
raddedge(u,cnt);
raddedge(cnt,u);
}
}
else
low[u]=min(low[u],dfn[v]);
}
}
//pre
void dfs1(int u,int f=0)
{
dep[u]=dep[f]+1;
siz[u]=1;
fa[u]=f;
int maxson=0;
for(int i=rhead[u];i;i=re[i].nxt)
{
int v=re[i].v;
if(v==f)
continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>maxson)
{
maxson=siz[v];
son[u]=v;
}
}
}
void dfs2(int u,int t)
{
dfn[u]=++idx;
p[idx]=u;
top[u]=t;
if(!son[u])
return;
dfs2(son[u],t);
for(int i=rhead[u];i;i=re[i].nxt)
{
int v=re[i].v;
if(v==fa[u]||v==son[u])
continue;
dfs2(v,v);
}
}
//stree
void pushup(int idx)
{
t[idx].val=min(t[2*idx].val,t[2*idx+1].val);
}
void build(int idx,int l,int r)
{
t[idx].l=l,t[idx].r=r;
if(l==r)
{
t[idx].val=a[p[l]];
return;
}
int mid=l+r>>1;
build(2*idx,l,mid);
build(2*idx+1,mid+1,r);
pushup(idx);
}
void update(int idx,int pos,int val)
{
if(t[idx].l>pos||t[idx].r<pos)
return;
if(t[idx].l==t[idx].r)
{
t[idx].val=val;
return;
}
int mid=t[idx].l+t[idx].r>>1;
if(pos<=mid)
update(2*idx,pos,val);
else
update(2*idx+1,pos,val);
pushup(idx);
}
int query(int idx,int l,int r)
{
if(t[idx].l>r||t[idx].r<l)
return mod;
if(l<=t[idx].l&&t[idx].r<=r)
return t[idx].val;
int mid=t[idx].l+t[idx].r>>1;
int cnt=mod;
if(l<=mid)
cnt=min(cnt,query(2*idx,l,r));
if(mid+1<=r)
cnt=min(cnt,query(2*idx+1,l,r));
return cnt;
}
int querypath(int u,int v)
{
int cnt=mod;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
cnt=min(cnt,query(1,dfn[top[u]],dfn[u]));
u=fa[top[u]];
}
if(dep[u]>dep[v])
swap(u,v);
cnt=min(cnt,query(1,dfn[u],dfn[v]));
return cnt;
}
//LCA
void dfs(int u,int f=0)
{
st[u][0]=f;
//dep[u]=dep[f]+1;
for(int i=1;i<=__lg(dep[u]);i++)
{
st[u][i]=st[st[u][i-1]][i-1];
}
for(int i=rhead[u];i;i=re[i].nxt)
{
int v=re[i].v;
if(v==f)
continue;
dfs(v,u);
}
}
int LCA(int u,int v)
{
if(dep[u]<dep[v])
swap(u,v);
while(dep[u]!=dep[v])
{
u=st[u][__lg(dep[u]-dep[v])];
}
if(u==v)
return u;
for(int i=__lg(dep[u]);i>=0;i--)
{
if(st[u][i]!=st[v][i])
{
u=st[u][i];
v=st[v][i];
}
}
return st[u][0];
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>q;
cnt=n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
cin>>u>>v;
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
s.pop();
}
}
idx=0;
dfs1(1);
dfs2(1,1);
for(int i=n+1;i<=cnt;i++)
{
a[i]=mod;
for(int j=rhead[i];j;j=re[j].nxt)
{
int v=re[j].v;
if(v==fa[i])
continue;
ms[i].insert(a[v]);
}
a[i]=*ms[i].begin();
}
build(1,1,cnt);
dfs(1);
while(q--)
{
cin>>con;
if(con=='C')
{
int pos,val;
cin>>pos>>val;
if(fa[pos]>n)
{
int f=fa[pos];
ms[f].erase(ms[f].find(a[pos]));
ms[f].insert(val);
update(1,dfn[f],*ms[f].begin());
}
a[pos]=val;
update(1,dfn[pos],val);
}
else
{
int u,v;
cin>>u>>v;
int ans=querypath(u,v),lca=LCA(u,v);
if(lca>n)
ans=min(ans,a[fa[lca]]);
cout<<ans<<endl;
}
}
return 0;
}
//Skadi_H