题意:
操作一:将根节点变为x
操作二:将x到y的点权变为v
操作三:询问x及其子树中最小点权
按照1进行树剖即可
如果 x为根节点 那么输出线段树最小值即可
如果x不在1-root的路径上 那么正常输出x的子树即可(为+siz)
如果x在1-root的路径上 设x在1-root上的儿子节点为y 输出除了 id[y],id[y]+siz[y]-1 的其他部分的最小值即可 也就是 1----d[y]-1 id[y]+siz[y]-----n
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ///////////////////////////////////// const int N=1e6+100; ll minn[N<<2],col[N<<2]; int n,m,root,T; ll w[N],node[N]; void build(int l,int r,int pos) { if(l==r){minn[pos]=w[l];return ;} int m=(l+r)>>1; build(l,m,pos<<1);build(m+1,r,pos<<1|1); minn[pos]=min(minn[pos<<1],minn[pos<<1|1]); } void down(int pos) { if(!col[pos])return ; col[pos<<1|1]=col[pos<<1]=minn[pos<<1]=minn[pos<<1|1]=col[pos]; col[pos]=0; } void upsum(int L,int R,ll v,int l,int r,int pos) { if(L<=l&&r<=R){col[pos]=minn[pos]=v;return ;} down(pos);int m=(l+r)>>1; if(L<=m)upsum(L,R,v,l,m,pos<<1); if(R>m)upsum(L,R,v,m+1,r,pos<<1|1); minn[pos]=min(minn[pos<<1],minn[pos<<1|1]); } ll qmin(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R)return minn[pos]; int m=(l+r)>>1;ll ans=inf;down(pos); if(L<=m)ans=min(ans,qmin(L,R,l,m,pos<<1)); if(R>m)ans=min(ans,qmin(L,R,m+1,r,pos<<1|1)); minn[pos]=min(minn[pos<<1],minn[pos<<1|1]); return ans; } int fa[N][30],id[N],ncnt,dep[N],son[N],siz[N],top[N],head[N],pos; struct Edge{int to,nex;}edge[N<<1]; void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;} void dfs1(int x,int f) { fa[x][0]=f;son[x]=0;siz[x]=1;dep[x]=dep[f]+1; rep(i,1,T) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to;if(v==f)continue; dfs1(v,x);siz[x]+=siz[v]; if(siz[son[x]]<siz[v])son[x]=v; } } void dfs2(int x,int topf) { top[x]=topf;id[x]=++ncnt;w[ncnt]=node[x]; if(son[x])dfs2(son[x],topf); for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to;if(v==fa[x][0]||v==son[x])continue; dfs2(v,v); } } void UPsum(int x,int y,int v) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); upsum(id[top[x]],id[x],v,1,n,1); x=fa[top[x]][0]; } if(dep[x]>dep[y])swap(x,y); upsum(id[x],id[y],v,1,n,1); } int get1(int x,int k) { repp(i,T,0) if(k>=(1<<i)) k-=(1<<i),x=fa[x][i]; return x; } int main() { scanf("%d%d",&n,&m);T=log2(n); rep(i,1,n-1) { int a,b;scanf("%d%d",&a,&b);add(a,b);add(b,a); } rep(i,1,n)scanf("%lld",&node[i]); scanf("%d",&root); dfs1(1,1); dfs2(1,1); build(1,n,1);int a,b,c,y;ll d; while(m--) { scanf("%d%d",&a,&b); if(a==1)root=b; else if(a==2)scanf("%d%lld",&c,&d),UPsum(b,c,d); else { int x=b; if(root==b){printf("%lld ",minn[1]);continue;} if(dep[x]<dep[root]&&fa[y=get1(root,dep[root]-dep[x]-1)][0]==x) { ll p,q; p=qmin(1,id[y]-1,1,n,1); if(id[y]+siz[y]<=n) q=qmin(id[y]+siz[y],n,1,n,1); else q=(1LL<<31)+1; printf("%lld ",min(q,p)); } else printf("%lld ",qmin(id[x],id[x]+siz[x]-1,1,n,1)); } } return 0; }