树剖+线段树+dfs序+LCA--bzoj3083 遥远的国度

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84391468

传送门
一道树剖线段树维护 d f s dfs 序的好题,首先换根的时候考虑一个点的子树的变化,分类讨论:
设当前根为 r o o t root ,询问点为 x x
1. x r o o t x 1.x在root的子树中,x的子树不变
2. x r o o t x 2.x不在root到原根的路径上,x的子树不变
3. x r o o t x r o o t v x v 3.x在root到原根的路径上,设离x最近的在root到原根路径上的点为v,则x的子树为v的子树的补集。

所以在第三种情况的时候只需要倍增求出 v v
答案就是 m i n ( q u e r y ( 1 , 1 , d f n [ v ] 1 ) , q u e r y ( 1 , d f n [ v ] + s i z [ v ] , n ) min(query(1,1,dfn[v]-1),query(1,dfn[v]+siz[v],n)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ls cur<<1
#define rs cur<<1|1
#define N 100005
#define inf 0x7fffffff
using namespace std;

inline int rd(){
	int x=0,f=1;char c=' ';
	while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}

int n,m,val[N],dfn[N],f[N],dep[N],siz[N],son[N],rk[N],top[N];
int num,cnt,head[N],root,opt,prert,g[N][18];

struct EDGE{
	int to,nxt;
}edge[N<<1];
inline void add(int x,int y){
	edge[++cnt].to=y; edge[cnt].nxt=head[x]; head[x]=cnt;
}

void dfs1(int u,int fa){
	siz[u]=1; int maxson=-1;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(v==fa) continue;
		dep[v]=dep[u]+1; f[v]=u; g[v][0]=u;
		for(int j=1;j<=17;j++)
			g[v][j]=g[g[v][j-1]][j-1];
		dfs1(v,u); siz[u]+=siz[v];
		if(siz[v]>maxson) maxson=siz[v],son[u]=v;
	} return;
}

void dfs2(int u,int t){
	dfn[u]=++num; rk[num]=u; top[u]=t;
	if(!son[u]) return;
	dfs2(son[u],t);
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(!dfn[v]) dfs2(v,v);
	} return;
}

struct Node{
	int l,r,mn,lazy;
}node[N<<2];

inline void pushup(int cur){
	node[cur].mn=min(node[ls].mn,node[rs].mn);
}
inline void pushdown(int cur){
	if(node[cur].lazy){
		node[ls].mn=node[rs].mn=node[ls].lazy=node[rs].lazy=node[cur].lazy;
		node[cur].lazy=0;
	}
}
void build(int cur,int L,int R){
	if(L==R){
		node[cur].l=node[cur].r=L; node[cur].mn=val[rk[L]];
		return ;
	}
	int mid=(L+R)>>1;
	build(ls,L,mid); build(rs,mid+1,R);
	node[cur].l=node[ls].l,node[cur].r=node[rs].r;
	pushup(cur); return;
}

void update(int cur,int L,int R,int c){
	if(L<=node[cur].l && node[cur].r<=R){
		node[cur].mn=c; node[cur].lazy=c;
		return;
	}
	pushdown(cur);
	int mid=(node[cur].l+node[cur].r)>>1;
	if(L<=mid) update(ls,L,R,c);
	if(mid<R) update(rs,L,R,c);
	pushup(cur); return;
}

int query(int cur,int L,int R){
	if(L<=node[cur].l && node[cur].r<=R) return node[cur].mn;
	pushdown(cur);
	int mid=(node[cur].l+node[cur].r)>>1,res=inf;
	if(L<=mid) res=min(res,query(ls,L,R));
	if(mid<R) res=min(res,query(rs,L,R));
	return res;
}

inline void change(int x,int y,int c){
	while(top[x]!=top[y]){
		if(dep[top[x]]<=dep[top[y]]) swap(x,y);
		update(1,dfn[top[x]],dfn[x],c);
		x=f[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	update(1,dfn[x],dfn[y],c); return;
}
inline int ask(int x,int y){
	int res=inf;
	while(top[x]!=top[y]){
		if(dep[top[x]]<=dep[top[y]]) swap(x,y);
		res=min(res,query(1,dfn[top[x]],dfn[x]));
		x=f[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	res=min(res,query(1,dfn[x],dfn[y]));
	return res;
}
inline int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]>=dep[top[y]]) x=f[top[x]];
		else y=f[top[y]];
	}
	return dep[x]<dep[y]?x:y;
}

inline int find(int x,int len){
	for(int i=0;i<=17;i++)
		if(len&(1<<i)) x=g[x][i];
	return x;
}

inline int solve(int x){
	if(x==root) return query(1,1,n);
	if(dfn[x]>=dfn[root] && dfn[x]<=dfn[root]+siz[root]-1) 
		return query(1,dfn[x],dfn[x]+siz[x]-1);
	if(LCA(x,root)==x){
		int y=find(root,dep[root]-dep[x]-1);
		return min(query(1,1,dfn[y]-1),query(1,dfn[y]+siz[y],n));
	}
	return query(1,dfn[x],dfn[x]+siz[x]-1);
}

int main(){
	n=rd(); m=rd();
	for(int i=1;i<n;i++){
		int x=rd(),y=rd();
		add(x,y); add(y,x);
	}
	for(int i=1;i<=n;i++) val[i]=rd();
	prert=root=rd(); dfs1(root,root); dfs2(root,root);
	build(1,1,n);
	while(m--){
		opt=rd();
		if(opt==1) root=rd();
		if(opt==2){
			int x=rd(),y=rd(),z=rd();
			change(x,y,z);
		}
		if(opt==3) printf("%d\n",solve(rd()));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/84391468