裸的树剖 换根之后对于一个询问只需要判断当前根是否是在原树中被该节点包含就好了
人蠢代码长 没办法
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> using namespace std; char c; inline void read(long long &a) { a=0;do c=getchar();while(c<'0'||c>'9'); while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar(); } long long Heavy_Chain_Begin[100001],Heavy_Chain_Data[100001],Heavy_Chain_Place[100001],Heavy_Chain_End[100001]; long long Heavy_Son[100001],Con_Son[100001]; bool done[1000001]; long long deep[10000001]; struct Chain { Chain* next; long long data; long long other; Chain(){next=NULL; } }*Son[100001],*head[100001]; const long long INF=1ll<<61; struct Segement { long long l,r; long long data; long long flag; }Segement_Tree[1000001]; void Build_Segement_Tree(long long place,long long l,long long r) { Segement_Tree[place].l=l; Segement_Tree[place].r=r; Segement_Tree[place].flag=false; if(l==r) { Segement_Tree[place].flag=true; Segement_Tree[place].data=Heavy_Chain_Data[l];return ; } Build_Segement_Tree(place<<1,l,(l+r)>>1); Build_Segement_Tree(place<<1|1,((l+r)>>1)+1,r); Segement_Tree[place].data=min(Segement_Tree[place<<1].data,Segement_Tree[place<<1|1].data); } inline void Pushdown(long long place) { Segement_Tree[place<<1].flag=Segement_Tree[place<<1|1].flag=true; Segement_Tree[place<<1].data=Segement_Tree[place<<1|1].data=Segement_Tree[place].data; Segement_Tree[place].flag=false; } void Segement_Change(long long place,long long l,long long r,long long data) { if(Segement_Tree[place].l>=l&&Segement_Tree[place].r<=r) {Segement_Tree[place].flag=true;Segement_Tree[place].data=data;return ; } if(Segement_Tree[place].flag) Pushdown(place); if(Segement_Tree[place<<1].r>=l) Segement_Change(place<<1,l,r,data); if(Segement_Tree[place<<1|1].l<=r) Segement_Change(place<<1|1,l,r,data); Segement_Tree[place].data=min(Segement_Tree[place<<1].data,Segement_Tree[place<<1|1].data); } long long Segement_Query(long long place,long long l,long long r) { long long data; if(l>r) return INF; if(Segement_Tree[place].flag) return Segement_Tree[place].data; if(l<=Segement_Tree[place].l&&r>=Segement_Tree[place].r) return Segement_Tree[place].data; data=INF; if(Segement_Tree[place<<1].r>=l) data=min(data,Segement_Query(place<<1,l,r)); if(Segement_Tree[place<<1|1].l<=r) data=min(data,Segement_Query(place<<1|1,l,r)); return data; } long long f[1000001]; void dfs(long long u) { done[u]=true; Heavy_Son[u]=0; Con_Son[u]++; Chain *j,*tp; for(j=head[u];j;j=j->next) if(!done[j->other]) { tp=new Chain;tp->next=Son[u];tp->other=j->other;Son[u]=tp; deep[j->other]=deep[u]+1; f[j->other]=u; dfs(j->other); Con_Son[u]+=Con_Son[j->other]; if(Con_Son[j->other]>Con_Son[Heavy_Son[u]])Heavy_Son[u]=j->other; } } long long Heavy_Con; long long Data[1000001]; long long Heavy_Chain_Node[1000001]; long long root,C_root; void dfs2(long long u,long long j) { Heavy_Chain_Begin[u]=j; Heavy_Chain_Place[u]=++Heavy_Con; Heavy_Chain_Data[Heavy_Con]=Data[u]; Heavy_Chain_Node[Heavy_Con]=u; if(!Heavy_Son[u]) goto end; dfs2(Heavy_Son[u],j); for(Chain *tp=Son[u];tp;tp=tp->next) if(tp->other!=Heavy_Son[u]) dfs2(tp->other,Heavy_Con+1); end:Heavy_Chain_End[u]=Heavy_Con; } inline long long Query(long long u) { Chain *tp; long long minx,maxx; if(u==C_root) return Segement_Query(1,1,Heavy_Con); if(Heavy_Chain_Place[u]<=Heavy_Chain_Place[C_root]&&Heavy_Chain_Place[C_root]<=Heavy_Chain_End[u]) { for(tp=Son[u];tp;tp=tp->next) if(Heavy_Chain_Place[tp->other]<=Heavy_Chain_Place[C_root]&&Heavy_Chain_Place[C_root]<=Heavy_Chain_End[tp->other]) { minx=Heavy_Chain_Place[tp->other]; maxx=Heavy_Chain_End[tp->other]; break; } return min(Segement_Query(1,1,minx-1),Segement_Query(1,maxx+1,Heavy_Con)); } else return Segement_Query(1,Heavy_Chain_Place[u],Heavy_Chain_End[u]); } inline long long LCA(long long a,long long b) { while(Heavy_Chain_Node[Heavy_Chain_Begin[a]]!=Heavy_Chain_Node[Heavy_Chain_Begin[b]]&&a!=root&&b!=root) if(deep[f[Heavy_Chain_Node[Heavy_Chain_Begin[a]]]]>=deep[f[Heavy_Chain_Node[Heavy_Chain_Begin[b]]]]) a=f[Heavy_Chain_Node[Heavy_Chain_Begin[a]]]; else b=f[Heavy_Chain_Node[Heavy_Chain_Begin[b]]]; return deep[a]>deep[b]?b:a; } inline void Change(long long a,long long b) { long long data; read(data); long long ancestor=LCA(a,b); while(a!=ancestor) { if(Heavy_Chain_Begin[a]==Heavy_Chain_Begin[ancestor]) {Segement_Change(1,Heavy_Chain_Place[ancestor],Heavy_Chain_Place[a],data);break ;} Segement_Change(1,Heavy_Chain_Begin[a],Heavy_Chain_Place[a],data); a=f[Heavy_Chain_Node[Heavy_Chain_Begin[a]]]; } while(b!=ancestor) { if(Heavy_Chain_Begin[b]==Heavy_Chain_Begin[ancestor]) {Segement_Change(1,Heavy_Chain_Place[ancestor],Heavy_Chain_Place[b],data);break ;} Segement_Change(1,Heavy_Chain_Begin[b],Heavy_Chain_Place[b],data); b=f[Heavy_Chain_Node[Heavy_Chain_Begin[b]]]; } Segement_Change(1,Heavy_Chain_Place[ancestor],Heavy_Chain_Place[ancestor],data); } inline void addside(long long a,long long b) { Chain *tp=new Chain; tp->other=b; tp->next=head[a]; head[a]=tp; } int main() { long long n,m,i,j,k,l; read(n),read(m); for(i=2;i<=n;i++) read(j),read(k),addside(j,k),addside(k,j); for(i=1;i<=n;i++)read(Data[i]); read(root),C_root=root; f[root]=root; dfs(root); dfs2(root,1); Build_Segement_Tree(1,1,Heavy_Con); for(i=1;i<=m;i++) { read(j); if (j==1) read(C_root); else if(j==2) read(k),read(l),Change(k,l); else read(k),printf("%lld\n",Query(k)); } return 0; }