[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号