记录编号 313715 评测结果 AAAAAAAAAAAAAAAAAA
题目名称 遥远的国度 最终得分 100
用户昵称 GravatarHzoi_chairman 是否通过 通过
代码语言 C++ 运行时间 3.157 s
提交时间 2016-10-01 21:48:18 内存使用 15.57 MiB
显示代码纯文本
/*
  Name: 遥远的国度
  Copyright: 
  Author: chairman
  Date: 01/10/16 18:58
  Description: 树剖,变根后不必重复dfs, 查询时分情况讨论
  			   如果root=x,则查询整棵树
			   如果lca(root,x)!=x,则查询x的子书
			   如果lca(root,x)==x,则找到root到x的路径上x的儿子,必须是最近的儿子(用倍增),然后查询整棵树中除这个儿子子树外的结点 
*/
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define maxn 101000
#define maxe 201000
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
int read()
{
	int x,f=1;
	char ch;
	while(ch=getchar(),!isdigit(ch))if(ch=='-')f=-1;
	x=ch-48;
	while(ch=getchar(),isdigit(ch))x=x*10+ch-48;
	return x*f;
}
void write(int x)
{
	if(x<0)putchar('-'),x=-x;
	int cnt=0;char ch[50];
	while(ch[++cnt]=x%10+48,x/=10);
	while(putchar(ch[cnt]),--cnt);
	putchar('\n');
}
struct edge
{
	int t,n;
}a[maxe];
int len,head[maxn];
void insert(int x,int y)
{
	a[++len].t=y;a[len].n=head[x];head[x]=len;
}
int D,n,m,size[maxn],son[maxn],fa[maxn][25],val[maxn],tp[maxn],dp[maxn],cnt,root,id[maxn],pos[maxn];
int ra[maxn<<2];
bool lazy[maxn<<2];
#define k a[i].t
void dfs1(int x)
{
	size[x]=1;
	for(int i=head[x];i;i=a[i].n)
	{
		if(fa[x][0]==k)continue;
		dp[k]=dp[x]+1;
		fa[k][0]=x;
		dfs1(k);
		size[x]+=size[k];
		if(size[son[x]]<size[k])son[x]=k;
	}
}
void dfs2(int x,int top)
{
	tp[x]=top;id[x]=++cnt;pos[cnt]=x;
	if(son[x])dfs2(son[x],top);
	for(int i=head[x];i;i=a[i].n)
	{
		if(fa[x][0]==k||son[x]==k)continue;
		dfs2(k,k);
	}
}
#undef k
void build(int rt,int l,int r)
{
	if(l==r)
	{
		ra[rt]=val[pos[l]];
		return ;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	ra[rt]=min(ra[rt<<1],ra[rt<<1|1]);
}
void update(int rt)
{
	ra[rt<<1]=ra[rt<<1|1]=ra[rt];
	lazy[rt]=0;
	lazy[rt<<1]=lazy[rt<<1|1]=1;
}
void change(int rt,int l,int r,int x,int y,int z)
{
	if(x<=l&&y>=r)
	{
		ra[rt]=z;
		lazy[rt]=1;
		return ;
	}
	if(lazy[rt])update(rt);
	int mid=(l+r)>>1;
	if(x<=mid)change(lson,x,y,z);
	if(y>mid)change(rson,x,y,z);
	ra[rt]=min(ra[rt<<1],ra[rt<<1|1]);
}
int query(int rt,int l,int r,int x,int y)
{
	if(x<=l&&y>=r)return ra[rt];
	if(lazy[rt])update(rt);
	int mid=(l+r)>>1;
	int ans=0x7f7f7f7f;
	if(x<=mid)ans=min(ans,query(lson,x,y));
	if(y>mid)ans=min(ans,query(rson,x,y));
	return ans;
}
int lca(int x,int y)
{
	int fx=tp[x],fy=tp[y];
	while(fx!=fy)
	{
		if(dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
		x=fa[fx][0];fx=tp[x];
	}
	if(dp[x]>dp[y])return y;
	else return x;
}
int find(int x,int y)
{
	for(int j=20;j>=0;j--)
		if(dp[fa[x][j]]>dp[y])x=fa[x][j];
	return x;
}
void tree_change(int x,int y,int z)
{
	int fx=tp[x],fy=tp[y];
	while(fx!=fy)
	{
		if(dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
		change(1,1,n,id[fx],id[x],z);
		x=fa[fx][0],fx=tp[x];
	}
	change(1,1,n,id[x],id[y],z);
}
int main()
{
	freopen("bbbbb.in","r",stdin);
	freopen("bbbbb.out","w",stdout);
	n=read(),m=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		insert(x,y);
		insert(y,x);
	}
	for(int i=1;i<=n;i++)val[i]=read();
	dfs1(1);
	dfs2(1,1);
	build(1,1,n);
	root=read();
	D=log(n*1.0)/log(2.0);
	for(int j=1;j<=D;j++)
		for(int i=1;i<=n;i++)
			fa[i][j]=fa[fa[i][j-1]][j-1];
	for(int i=1;i<=m;i++)
	{
		int type=read();
		if(type==1)root=read();
		if(type==2)
		{
			int x=read(),y=read(),z=read();
			tree_change(x,y,z);
		}
		if(type==3)
		{
			int x=read();
			if(x==root)
				write(query(1,1,n,1,n));
			else
			{
				int f=lca(root,x);
				if(f!=x)write(query(1,1,n,id[x],id[x]+size[x]-1));
				else
				{
					int y=find(root,x);
					write(min(query(1,1,n,1,id[y]-1),query(1,1,n,id[y]+size[y],n)));
				}
			}
		}
	}
	//system("pause");
}