圆方树模板题.
建出圆方树.
对于每个方点,只维护方点儿子的最小值,不维护方点父亲的值,这样的话每次修改只会改一个方点.
我们需要支持单点修改,链查询,求 lca.
LCT 可以非常方便地维护这些东西,然后如果 lca 是方点的话特判一下方点父亲的点值即可.
code:
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
#include <cstring>
#define setI(s) freopen(s".in","r",stdin)
#define setO(s) freopen(s".out","w",stdout)
#define setIO(s) setI(s),setO(s)
using namespace std;
const int N=2e5+5;
const int inf=1e9+2;
namespace lct {
#define lson s[x].ch[0]
#define rson s[x].ch[1]
struct data
{
int ch[2],rev,val,mi,f;
data(int x=inf) { ch[0]=ch[1]=0,val=mi=x; }
}s[N];
int sta[N];
int get(int x) { return s[s[x].f].ch[1]==x; }
int isr(int x) { return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; }
void pushup(int x)
{
s[x].mi=min(s[x].val,min(s[lson].mi,s[rson].mi));
}
void mark(int x)
{
if(!x) return;
swap(lson,rson),s[x].rev^=1;
}
void pushdown(int x)
{
if(s[x].rev)
mark(lson),mark(rson),s[x].rev=0;
}
void rotate(int x)
{
int old=s[x].f,fold=s[old].f,which=get(x);
if(!isr(old))
s[fold].ch[s[fold].ch[1]==old]=x;
s[old].ch[which]=s[x].ch[which^1];
if(s[old].ch[which])
s[s[old].ch[which]].f=old;
s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;
pushup(old),pushup(x);
}
void splay(int x)
{
int u=x,v=0,fa;
for(sta[++v]=u;!isr(u);u=s[u].f)
sta[++v]=s[u].f;
for(;v;--v)
pushdown(sta[v]);
for(u=s[u].f;(fa=s[x].f)!=u;rotate(x))
if(s[fa].f!=u)
rotate(get(fa)==get(x)?fa:x);
}
int Access(int x)
{
int y=0;
for(;x;y=x,x=s[x].f)
splay(x),rson=y,pushup(x);
return y;
}
void makert(int x)
{
Access(x),splay(x),mark(x);
}
void split(int x,int y)
{
makert(x),Access(y),splay(y);
}
void link(int x,int y)
{
s[x].f=y;
}
int get_lca(int x,int y)
{
Access(x);
return Access(y);
}
};
vector<int>G[N];
int val[N],dfn[N],low[N],S[N],tim,top,tot;
int hd[N],to[N],nex[N],edges,n,m,Q;
int fa[N];
multiset<int>mi[N];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void tarjan(int u)
{
dfn[u]=low[u]=++tim;
S[++top]=u;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(!dfn[v])
{
tarjan(v),low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
++tot;
G[tot].push_back(u);
G[u].push_back(tot);
for(int x=0;x!=v;--top)
{
x=S[top];
G[tot].push_back(x);
G[x].push_back(tot);
}
}
}
else low[u]=min(low[u],dfn[v]);
}
}
void dfs(int x,int ff)
{
if(ff)
lct::link(x,ff);
if(x<=n)
{
if(ff) mi[ff].insert(val[x]);
lct::s[x].val=lct::s[x].mi=val[x];
}
for(int i=0;i<G[x].size();++i)
{
int y=G[x][i];
if(y!=ff) fa[y]=x,dfs(y,x);
}
if(x>n)
{
lct::s[x].val=lct::s[x].mi=*mi[x].begin();
}
}
int main()
{
//setI("input");
scanf("%d%d%d",&n,&m,&Q);
for(int i=1;i<=n;++i)
scanf("%d",&val[i]);
for(int i=1;i<=m;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
tot=n;
for(int i=1;i<=n;++i)
if(!dfn[i])
tarjan(i);
dfs(1,0);
val[0]=inf;
for(int i=1;i<=Q;++i)
{
char ch[2];
int x,b;
scanf("%s%d%d",ch,&x,&b);
if(ch[0]=='C')
{
lct::splay(x);
lct::s[x].val=b;
lct::pushup(x);
if(fa[x])
{
mi[fa[x]].erase(mi[fa[x]].lower_bound(val[x]));
mi[fa[x]].insert(b);
lct::splay(fa[x]);
lct::s[fa[x]].val=*mi[fa[x]].begin();
lct::pushup(fa[x]);
}
val[x]=b;
// modify(val[x] -> b)
}
else
{
// query(a,b)
int lca=lct::get_lca(x,b);
if(lca<=n) lca=0;
lct::split(x,b);
printf("%d\n",min(lct::s[b].mi,val[fa[lca]]));
lct::makert(1);
}
}
return 0;
}