[bzoj3083]遥远的国度
遥远的国度
题解
如果没有换根的操作,那这道题就是一个板子题了。我们只需考虑在换根的情况下如何对其进行维护了。
我们发现,如果这个根在它的子树内的话,就是它所在的儿子会成为这个点的父亲,而其他点都会产生贡献,所以每次查询除这个儿子所在子树的区间即可。
所以这又成一个板子题了。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<set>
using namespace std;
#define MAXN 100005
typedef long long LL;
typedef pair<int,int> pii;
const int INF=0x7f7f7f7f;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int n,m,head[MAXN],tot,root,idx,td[MAXN];
int dep[MAXN],f[MAXN][22],siz[MAXN],wson[MAXN];
int val[MAXN],pre[MAXN],dfn[MAXN],ltp[MAXN];
int minn[MAXN<<2],lzy[MAXN<<2],father[MAXN];
struct edge{int to,nxt;}e[MAXN<<1];
void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
void dfs1(int u,int fa){
	dep[u]=dep[fa]+1;father[u]=f[u][0]=fa;siz[u]=1;
	for(int i=1;i<20;i++)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa)continue;
		dfs1(v,u);siz[u]+=siz[v];
		if(siz[v]>siz[wson[u]])wson[u]=v;
	}
}
void dfs2(int u,int tp){
	ltp[u]=tp;dfn[u]=++idx;pre[idx]=u;
	if(wson[u])dfs2(wson[u],tp);
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(dfn[v])continue;
		dfs2(v,v);
	}
	td[u]=idx;
}
void build(int rt,int l,int r){
	if(l==r)return (void)(minn[rt]=val[pre[l]]);
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
void pushdown(int rt){
	if(!lzy[rt])return;
	minn[rt<<1]=minn[rt<<1|1]=lzy[rt];
	lzy[rt<<1]=lzy[rt<<1|1]=lzy[rt];lzy[rt]=0;
}
int query(int rt,int l,int r,int al,int ar){
	if(l>r||l>ar||r<al)return INF;
	if(al<=l&&r<=ar)return minn[rt];
	int res=INF,mid=l+r>>1;pushdown(rt);
	if(al<=mid)res=min(res,query(rt<<1,l,mid,al,ar));
	if(ar>mid)res=min(res,query(rt<<1|1,mid+1,r,al,ar));
	return res; 
}
void updata(int rt,int l,int r,int al,int ar,int w){
	if(l>r||l>ar||r<al)return ;
	if(al<=l&&r<=ar)return (void)(lzy[rt]=minn[rt]=w);
	int mid=l+r>>1;pushdown(rt);
	updata(rt<<1,l,mid,al,ar,w);
	updata(rt<<1|1,mid+1,r,al,ar,w);
	minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}
void Chain_updata(int u,int v,int w){
	for(int fu=ltp[u],fv=ltp[v];fu^fv;u=father[ltp[u]],fu=ltp[u]){
		if(dep[fu]<dep[fv])swap(u,v),swap(fu,fv);
		updata(1,1,n,dfn[fu],dfn[u],w);
	}
	if(dep[u]>dep[v])swap(u,v);
	updata(1,1,n,dfn[u],dfn[v],w);
}
int findFa(int u,int k){for(int i=19;i>=0;i--)if(k&(1<<i))u=f[u][i];return u;}
signed main(){
	read(n);read(m);
	for(int i=1;i<n;i++){
		int u,v;read(u);read(v);
		addEdge(u,v);addEdge(v,u);
	}
	for(int i=1;i<=n;i++)read(val[i]);read(root);
	dfs1(1,0);dfs2(1,1);build(1,1,n);
	for(int i=1;i<=m;i++){
		int opt;read(opt);
		if(opt==1)read(root);
		if(opt==2){
			int u,v,w;read(u);read(v);read(w);
			Chain_updata(u,v,w);
		}
		if(opt==3){
			int u;read(u);
			if(u==root){printf("%d\n",minn[1]);continue;}
			if(dep[u]>=dep[root]||findFa(root,dep[root]-dep[u])!=u){
				printf("%d\n",query(1,1,n,dfn[u],td[u]));
				continue;
			}
			int v=findFa(root,dep[root]-dep[u]-1);
			printf("%d\n",min(query(1,1,n,1,dfn[v]-1),query(1,1,n,td[v]+1,n)));
		}
	}
	return 0;
} 
                    
                
                
            
        
浙公网安备 33010602011771号