洛谷 3979 BZOJ 3083 遥远的国度
【题解】
这道题除去根操作就是普通的树链剖分了。但是有换根操作怎么处理呢?
我们可以发现如果现在的根不在查询的点的子树里,那么对本次查询没有影响。如果现在的跟在查询的点x的子树里,那么答案将变为整棵树除去现在的根root所属的x的孩子的子树。
为了快速确定root属于x的哪一个孩子,我们可以写个倍增。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #define N 200010 6 #define LL long long 7 #define rg register 8 #define ls (u<<1) 9 #define rs (u<<1|1) 10 #define mid ((a[u].l+a[u].r)>>1) 11 using namespace std; 12 int n,m,tot,cnt,root=1,last[N],dep[N],siz[N],top[N],fa[N],hvy[N],dfn[N],pos[N],v[N],p[N][20]; 13 struct edge{ 14 int to,pre; 15 }e[N<<1]; 16 struct tree{ 17 int l,r,mn,num; bool mark; 18 }a[N<<2]; 19 inline int read(){ 20 int k=0,f=1; char c=getchar(); 21 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 22 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 23 return k*f; 24 } 25 void find(int u,int f){ 26 p[u][0]=f; 27 for (int i=1;i<=log2(dep[u]);i++) p[u][i]=p[p[u][i-1]][i-1]; 28 for (int i=last[u],to=e[i].to;i;i=e[i].pre,to=e[i].to) 29 if(to!=f) find(to,u); 30 } 31 void dfs1(int x){ 32 siz[x]=1; dep[x]=dep[fa[x]]+1; 33 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]){ 34 fa[to]=x; dfs1(to); siz[x]+=siz[to]; 35 if(siz[x]>siz[hvy[x]]) hvy[x]=to; 36 } 37 } 38 void dfs2(int x,int tp){ 39 top[x]=tp; dfn[x]=++cnt; pos[cnt]=x; 40 if(hvy[x]) dfs2(hvy[x],tp); 41 for(rg int i=last[x],to;i;i=e[i].pre)if((to=e[i].to)!=fa[x]&&to!=hvy[x]) 42 dfs2(to,to); 43 } 44 void build(int u,int l,int r){ 45 a[u].l=l; a[u].r=r; 46 if(l<r) build(ls,l,mid),build(rs,mid+1,r),a[u].mn=min(a[ls].mn,a[rs].mn); 47 else a[u].mn=v[pos[l]]; 48 } 49 inline void pushdown(int u){ 50 a[u].mark=0; a[ls].mark=a[rs].mark=1; 51 a[ls].num=a[rs].num=a[u].num; 52 a[ls].mn=a[rs].mn=a[u].mn; 53 } 54 void update(int u,int l,int r,int d){ 55 if(l<=a[u].l&&a[u].r<=r){ 56 a[u].mark=1; a[u].num=d; a[u].mn=d; 57 return; 58 } 59 if(a[u].mark) pushdown(u); 60 if(l<=mid) update(ls,l,r,d); 61 if(r>mid) update(rs,l,r,d); 62 a[u].mn=min(a[ls].mn,a[rs].mn); 63 } 64 int query(int u,int l,int r){ 65 if(l<=a[u].l&&a[u].r<=r) return a[u].mn; 66 if(a[u].mark) pushdown(u); int ret=2e9; 67 if(l<=mid) ret=min(ret,query(ls,l,r)); 68 if(r>mid) ret=min(ret,query(rs,l,r)); 69 return ret; 70 } 71 int main(){ 72 n=read(); m=read(); 73 for(rg int i=1;i<n;i++){ 74 int u=read(),v=read(); 75 e[++tot]=(edge){v,last[u]}; last[u]=tot; 76 e[++tot]=(edge){u,last[v]}; last[v]=tot; 77 } 78 for(rg int i=1;i<=n;i++) v[i]=read(); 79 root=read(); 80 dfs1(root); dfs2(root,root); build(1,1,n); find(root,0); 81 while(m--){ 82 int opt=read(); 83 if(opt==1) root=read(); 84 else if(opt==2){ 85 int x=read(),y=read(),d=read(),t1=top[x],t2=top[y]; 86 while(t1!=t2){ 87 if(dep[t1]<dep[t2]) swap(t1,t2),swap(x,y); 88 update(1,dfn[t1],dfn[x],d); 89 x=fa[t1]; t1=top[x]; 90 } 91 if(dep[x]>dep[y]) swap(x,y); 92 update(1,dfn[x],dfn[y],d); 93 } 94 else if(opt==3){ 95 int x=read(); 96 if(dfn[x]<dfn[root]&&dfn[root]<=dfn[x]+siz[x]-1){ 97 int y=root; 98 for(int i=log2(dep[y]-dep[x]);i>=0&&(dep[x]+1)!=dep[y];i--) 99 if(dep[p[y][i]]>=dep[x]+1) y=p[y][i]; 100 int ans=2e9; 101 ans=min(ans,query(1,1,dfn[y]-1)); 102 ans=min(ans,query(1,dfn[y]+siz[y],n)); 103 printf("%d\n",ans); 104 } 105 else{ 106 if(x==root) printf("%d\n",query(1,1,n)); 107 else printf("%d\n",query(1,dfn[x],dfn[x]+siz[x]-1)); 108 } 109 } 110 } 111 return 0; 112 }