版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88808950
分析:
圆方树板子题。
每个点方点放个multiset维护其子圆点的最小值
询问和修改用树剖
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#define SF scanf
#define PF printf
#define MAXN 200010
#define INF 0x3FFFFFFF
using namespace std;
typedef pair<int,int> pii;
struct node{
int u,v;
node () {}
node (int u1,int v1):u(u1),v(v1) {}
}Edge[MAXN];
int dfn[MAXN],low[MAXN],cnt;
vector<int> a[MAXN];
int st[MAXN],tp,n2,tot;
void dfs(int x,int fa=0){
dfn[x]=low[x]=++cnt;
st[++tp]=x;
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==fa)
continue;
if(dfn[u]==0){
dfs(u,x);
low[x]=min(low[x],low[u]);
if(low[u]>=dfn[x]){
n2++;
Edge[++tot]=node(n2,x);
while(1){
Edge[++tot]=node(n2,st[tp]);
if(st[tp--]==u)
break;
}
}
}
else
low[x]=min(low[x],dfn[u]);
}
}
multiset<int> val[MAXN];
int son[MAXN],siz[MAXN];
int w[MAXN],n;
void prepare(int x,int fa=0){
if(fa>n)
val[fa].insert(w[x]);
siz[x]=1;
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==fa)
continue;
prepare(u,x);
siz[x]+=siz[u];
if(son[x]==0||siz[son[x]]<siz[u])
son[x]=u;
}
}
int tpd[MAXN];
int rk[MAXN],faz[MAXN],dep[MAXN];
void build_tree(int x,int tpx,int fa=0){
tpd[x]=tpx;
faz[x]=fa;
dfn[x]=++cnt;
dep[x]=dep[fa]+1;
rk[cnt]=x;
if(son[x]){
build_tree(son[x],tpx,x);
for(int i=0;i<int(a[x].size());i++){
int u=a[x][i];
if(u==fa||u==son[x])
continue;
build_tree(u,u,x);
}
}
}
int tree[MAXN*4];
void build(int id,int l,int r){
if(l==r){
if(rk[l]<=n)
tree[id]=w[rk[l]];
else
tree[id]=*val[rk[l]].begin();
return ;
}
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
tree[id]=min(tree[id<<1],tree[id<<1|1]);
}
void update(int id,int l,int r,int pos){
if(l==r){
if(rk[l]<=n)
tree[id]=w[rk[l]];
else
tree[id]=*val[rk[l]].begin();
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)
update(id<<1,l,mid,pos);
else
update(id<<1|1,mid+1,r,pos);
tree[id]=min(tree[id<<1],tree[id<<1|1]);
}
int ask(int id,int l,int r,int pl,int pr){
if(l>=pl&&r<=pr)
return tree[id];
int mid=(l+r)>>1;
int res=INF;
if(pl<=mid)
res=ask(id<<1,l,mid,pl,pr);
if(pr>mid)
res=min(res,ask(id<<1|1,mid+1,r,pl,pr));
return res;
}
pii query(int u,int v){
if(dep[tpd[u]]<dep[tpd[v]]||(dep[tpd[u]]==dep[tpd[v]]&&dep[u]<dep[v]))
swap(u,v);
if(tpd[u]==tpd[v])
return make_pair(ask(1,1,n2,dfn[v],dfn[u]),v);
pii res=query(faz[tpd[u]],v);
res.first=min(res.first,ask(1,1,n2,dfn[tpd[u]],dfn[u]));
return res;
}
char s[20];
int main(){
int m,q,u,v;
SF("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
SF("%d",&w[i]);
for(int i=1;i<=m;i++){
SF("%d%d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
}
n2=n;
dfs(1);
for(int i=1;i<=n;i++)
a[i].clear();
for(int i=1;i<=tot;i++){
// PF("[%d %d]\n",Edge[i].u,Edge[i].v);
a[Edge[i].u].push_back(Edge[i].v);
a[Edge[i].v].push_back(Edge[i].u);
}
prepare(1);
cnt=0;
build_tree(1,1);
build(1,1,n2);
for(int i=1;i<=q;i++){
SF("%s",&s);
if(s[0]=='A'){
SF("%d%d",&u,&v);
pii res=query(u,v);
int x=res.second;
int ans=res.first;
if(x>n)
ans=min(ans,w[faz[x]]);
PF("%d\n",ans);
}
else{
SF("%d%d",&u,&v);
if(faz[u]>n){
val[faz[u]].erase(val[faz[u]].find(w[u]));
w[u]=v;
val[faz[u]].insert(w[u]);
update(1,1,n2,dfn[faz[u]]);
}
w[u]=v;
update(1,1,n2,dfn[u]);
}
}
}