遥远的国度

应该是个已经做烂了的经典套路题

虽然题目要求换根
但是实际上并不需要

只要分情况讨论即可

如果查询的\(x=root\)直接查询整颗树

如果\(x\)\(root\)的祖先相当于把整颗树拎起来
查询的实际上是整颗树除了\(root\)所在的以\(x\)的儿子为根节点的子树的部分

否则查询的还是\(x\)的子树

具体可以想象一下\(root\)\(x\)的情况,想象一下把从\(root\)整颗树拎起来会变成什么样

然后就是树剖板子了

#include<bits/stdc++.h>

using namespace std;

#define gc c=getchar()
#define r(x) read(x)
#define ls (rt<<1)
#define rs (rt<<1|1)

template<typename T>
inline void read(T&x){
    x=0;T k=1;char gc;
    while(!isdigit(c)){if(c=='-')k=-1;gc;}
    while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
}

const int N=100005;

vector<int> G[N];

int ac[N][20],dep[N],siz[N],son[N];
void dfs1(int x,int f){
	ac[x][0]=f;
	dep[x]=dep[f]+1;
	siz[x]=1;
	for(int i=1;(ac[x][i]=ac[ac[x][i-1]][i-1]);++i);
	for(int i=0;i<G[x].size();++i){
		int v=G[x][i];
		if(v==f)continue;
		dfs1(v,x);
		siz[x]+=siz[v];
		if(siz[v]>siz[son[x]])son[x]=v;
	}
}

int top[N],dfn[N],ptn[N],dfs_clock;
void dfs2(int x,int t){
    top[x]=t;
    dfn[x]=++dfs_clock;
    ptn[dfs_clock]=x;
    if(son[x])dfs2(son[x],t);
    for(int i=0;i<G[x].size();++i){
        int v=G[x][i];
        if((v==ac[x][0])||(v==son[x]))continue;
		dfs2(v,v);
    }
}

inline int find(int x,int t){
	for(int i=17;~i;--i){
		if(dep[x]-dep[t]>(1<<i))x=ac[x][i];
	}
	assert(ac[x][0]==t);
	return x;
}

struct Seg{
	int min,tag;
}tr[N<<2];

int a[N];

inline void update(int rt){
	tr[rt].min=min(tr[ls].min,tr[rs].min);
}

inline void pushdown(int rt){
	if(tr[rt].tag){
		tr[ls].min=tr[rs].min=tr[ls].tag=tr[rs].tag=tr[rt].tag;
		tr[rt].tag=0;
	}
}

void build(int rt,int l,int r){
	if(l==r){
		tr[rt].min=a[ptn[l]];
		return ;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	update(rt);
}

void modify(int rt,int l,int r,int x,int y,int v){
	if(x<=l&&r<=y){
		tr[rt].min=tr[rt].tag=v;
		return ;
	}
	pushdown(rt);
	int mid=(l+r)>>1;
	if(x<=mid)modify(ls,l,mid,x,y,v);
	if(y>mid)modify(rs,mid+1,r,x,y,v);
	update(rt);
}

int query(int rt,int l,int r,int x,int y){
	if(x>y)return 1e9;
	if(x<=l&&r<=y)return tr[rt].min;
	pushdown(rt);
	int mid=(l+r)>>1;
	if(y<=mid)return query(ls,l,mid,x,y);
	else if(x>mid)return query(rs,mid+1,r,x,y);
	else return min(query(ls,l,mid,x,y),query(rs,mid+1,r,x,y));
}

int root,n,m;

inline void modify(int u,int v,int w){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        modify(1,1,n,dfn[top[u]],dfn[u],w);
        u=ac[top[u]][0];
    }
    if(dep[u]>dep[v])swap(u,v);
    modify(1,1,n,dfn[u],dfn[v],w);
    return ;
}

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

int main(){
	r(n),r(m);
	for(int i=1,u,v;i<n;++i){
		r(u),r(v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	for(int i=1;i<=n;++i)r(a[i]);
	r(root);
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,n);
	for(int i=1,opt,l,r,x;i<=m;++i){
		r(opt);
		if(opt==1)r(root);
		else if(opt==2){
			r(l),r(r),r(x);
			modify(l,r,x);
		}
		else {
			r(x);
			printf("%d\n",query(x));
		}
	}
}

posted @ 2018-10-20 19:38  NamelessOIer  阅读(197)  评论(0编辑  收藏  举报