3083: 遥远的国度
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 4426 Solved: 1190
[Submit][Status][Discuss]
Description
描述
zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。
问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。
Input
第1行两个整数n m,代表城市个数和操作数。
第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
第n+1行,有n个整数,代表所有点的初始防御值。
第n+2行一个整数 id,代表初始的首都为id。
第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。
Output
对于每个opt=3的操作,输出一行代表对应子树的最小点权值。
Sample Input
3 7
1 2
1 3
1 2 3
1
3 1
2 1 1 6
3 1
2 2 2 5
3 1
2 3 3 4
3 1
Sample Output
1
2
3
4
提示
对于20%的数据,n<=1000 m<=1000。
对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。
对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。
对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。
对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。
HINT
Source
zhonghaoxi提供
sol:
考虑有换根,显然不能lct。考虑用树剖来做,分类小讨论一波,容易发现,rt=x的时候就是整个子树,x在rt到根的路径上时就是整个树去掉x到rt方向上第一个点的子树,这个在树剖上跑一下就行了,不在重链上直接跳,否则用dfs序取出重链上的某个距离上的点。然后就是把dfs序分成2个区间求解。否则就是正常的求子树。
一开始以为权值能是0,网上搞了一份代码下来拍,把tag值改成1e15,结果标记下放完tag=0,调了1h可以说是很灵性了。
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline int read()
{
char c;
bool pd=0;
while((c=getchar())>'9'||c<'0')
if(c=='-') pd=1;
int res=c-'0';
while((c=getchar())>='0'&&c<='9')
res=(res<<3)+(res<<1)+c-'0';
return pd?-res:res;
}
const int N=410000;
int dep[N],fa[N],top[N],son[N],size[N],dfn[N],rev[N];
int fir[N],go[N],nex[N],tot;
inline void add(int x,int y)
{
nex[++tot]=fir[x];fir[x]=tot;go[tot]=y;
nex[++tot]=fir[y];fir[y]=tot;go[tot]=x;
}
inline void dfs1(int u)
{
dep[u]=dep[fa[u]]+1;
size[u]=1;
int e,v;
for(int e=fir[u];v=go[e],e;e=nex[e])
if(v!=fa[u])
{
fa[v]=u;
dfs1(v);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
inline void dfs2(int u,int d)
{
dfn[u]=++dfn[0];
rev[dfn[0]]=u;
top[u]=d;
if(son[u]) dfs2(son[u],d);
else return;
int e,v;
for(e=fir[u];v=go[e],e;e=nex[e])
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
typedef long long ll;
ll Min[N],tag[N],a[N];
inline void updata(int k)
{
Min[k]=min(Min[k<<1],Min[k<<1|1]);
}
inline void build(int k,int l,int r)
{
tag[k]=1e15;
if(l==r)
{
Min[k]=a[rev[l]];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
updata(k);
}
inline void tag_down(int k)
{
if(tag[k]!=1e15)
{
Min[k<<1]=tag[k];
Min[k<<1|1]=tag[k];
tag[k<<1]=tag[k];
tag[k<<1|1]=tag[k];
tag[k]=1e15;
}
}
inline void modify(int k,int l,int r,int L,int R,ll v)
{
if(L<=l&&r<=R)
{
Min[k]=v;
tag[k]=v;
return;
}
tag_down(k);
int mid=l+r>>1;
if(mid>=L) modify(k<<1,l,mid,L,R,v);
if(mid< R) modify(k<<1|1,mid+1,r,L,R,v);
updata(k);
}
inline void query(int k,int l,int r,int L,int R,ll &res)
{
if(L<=l&&r<=R)
{
res=min(res,Min[k]);
return;
}
int mid=l+r>>1;
tag_down(k);
if(mid>=L) query(k<<1,l,mid,L,R,res);
if(mid< R) query(k<<1|1,mid+1,r,L,R,res);
}
int n,m;
inline void modify(int x,int y,ll v)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
modify(1,1,n,dfn[fx],dfn[x],v);
x=fa[fx];fx=top[x];
}
if(dep[x]<dep[y]) swap(x,y);
modify(1,1,n,dfn[y],dfn[x],v);
}
inline int lca(int x,int y)
{
int fx=top[x];
while(dep[fx]>y)
x=fa[fx],fx=top[x];
return rev[dfn[x]-dep[x]+y];
}
int rt,Lca;
ll ans;
int main()
{
// freopen("3083.in","r",stdin);
// freopen("3083.out","w",stdout);
n=read();
m=read();
for(int i=2;i<=n;++i) add(read(),read());
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
dfs1(1);
dfs2(1,1);
build(1,1,n);
rt=read();
for(int i=1;i<=m;++i)
{
int tp,x,y;
ll z;
tp=read();
x=read();
if(tp==1) rt=x;
if(tp==2)
{
y=read();
scanf("%lld",&z);
modify(x,y,z);
}
if(tp==3)
{
ans=1e15;
if(rt==x) ans=Min[1];
else if(dfn[x]<=dfn[rt]&&dfn[rt]<=dfn[x]+size[x]-1)
{
Lca=lca(rt,dep[x]+1);
if(Lca!=1) query(1,1,n,1,dfn[Lca]-1,ans);
if(dfn[Lca]+size[Lca]<=n) query(1,1,n,dfn[Lca]+size[Lca],n,ans);
}
else query(1,1,n,dfn[x],dfn[x]+size[x]-1,ans);
printf("%lld\n",ans);
}
}
}