【圆方树】CodeForces487E Tourists

版权声明:本文为博主原创文章,未经博主允许不得转载。 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]);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/88808950