3083: 遥远的国度
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 4587 Solved: 1255
[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
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
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。
若 u==root
查询dfn在[1,n]的点
若 u在root的子树内
查询以选定假根为根内的子树
若 u不在root到选定假根的链上
查询以选定假根为根内的子树
若 u在root到选定假根的链上
发现现在u的子树就是整棵树减去u往root方向向下那个节点的子树
于是倍增求那个点然后整个dfs序就是分成两段了啊
#include<cmath>
#include<ctime>
#include<cstdio>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef double db;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=10*x+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=100100;
int last[N],ecnt;
struct EDGE{int to,nt;}e[N<<1];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}
int n,m,root,V[N];
int top[N],dfn[N],size[N],pos[N],tim;
int dep[N],anc[N][20];
inline int get_lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
int len=dep[u]-dep[v];
for(int i=0;(1<<i)<=len;++i)
if((1<<i)&len)
u=anc[u][i];
if(u==v) return u;
for(int i=17;~i;--i)
if(anc[u][i]!=anc[v][i])
u=anc[u][i],v=anc[v][i];
return anc[u][0];
}
inline int jump(int u,int aim)
{
int len=dep[u]-aim;
for(int i=0;(1<<i)<=len;++i)
if((1<<i)&len)
u=anc[u][i];
return u;
}
namespace decomposition
{
int son[N];
void dfs_1(int u,int fa)
{
size[u]=1;
for(int i=1;(1<<i)<=dep[u];++i)
anc[u][i]=anc[anc[u][i-1]][i-1];
for(int i=last[u],v;i;i=e[i].nt)
if(fa!=(v=e[i].to))
{
dep[v]=dep[u]+1,
anc[v][0]=u,
dfs_1(v,u),
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void dfs_2(int u,int fa)
{
if(!top[u]) top[u]=u;
dfn[u]=++tim,pos[tim]=u;
if(son[u])
top[son[u]]=top[u],dfs_2(son[u],u);
for(int i=last[u],v;i;i=e[i].nt)
if((v=e[i].to)!=fa && v!=son[u])
dfs_2(v,u);
}
void Main()
{
dfs_1(1,0),
dfs_2(1,0);
}
}
int mn[N<<2],tag[N<<2];
inline void pushdown(int k)
{
if(tag[k])
{
mn[k<<1]=mn[k<<1|1]=
tag[k<<1]=tag[k<<1|1]=tag[k];
tag[k]=0;
}
}
inline void pushup(int k)
{mn[k]=min(mn[k<<1],mn[k<<1|1]);}
void build(int k,int l,int r)
{
if(l==r){mn[k]=V[pos[l]];return ;}
int mid=(l+r)>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
pushup(k);
}
void modify(int k,int l,int r,int x,int y,int val)
{
if(l>=x && r<=y)
{
tag[k]=mn[k]=val;
return ;
}
int mid=(l+r)>>1;pushdown(k);
if(x<=mid) modify(k<<1,l,mid,x,y,val);
if(y>mid) modify(k<<1|1,mid+1,r,x,y,val);
pushup(k);
}
int query(int k,int l,int r,int x,int y)
{
if(x>y) return INT_MAX;
if(l>=x && r<=y) return mn[k];
int mid=(l+r)>>1;pushdown(k);
if(y<=mid) return query(k<<1,l,mid,x,y);
if(x>mid) return query(k<<1|1,mid+1,r,x,y);
return min(query(k<<1,l,mid,x,y),query(k<<1|1,mid+1,r,x,y));
}
void get_modify(int u,int v,int val)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
modify(1,1,n,dfn[top[u]],dfn[u],val);
u=anc[top[u]][0];
}
if(dep[u]<dep[v]) swap(u,v);
modify(1,1,n,dfn[v],dfn[u],val);
}
int get_query(int u,int v,int val)
{
int res(INT_MAX);
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
res=min(res,query(1,1,n,dfn[top[u]],dfn[u]));
u=anc[top[u]][0];
}
if(dep[u]<dep[v]) swap(u,v);
res=min(res,query(1,1,n,dfn[v],dfn[u]));
return res;
}
int get_ans(int u)
{
if(u==root) return query(1,1,n,1,n);
if(dfn[u]>=dfn[root] && dfn[u]<=dfn[root]+size[root]-1)
return query(1,1,n,dfn[u],dfn[u]+size[u]-1);
int lca=get_lca(u,root);
if(lca==u)
{
u=jump(root,dep[u]+1);
return min(query(1,1,n,1,dfn[u]-1),query(1,1,n,dfn[u]+size[u],n));
}
else return query(1,1,n,dfn[u],dfn[u]+size[u]-1);
}
int main()
{
n=read(),m=read();
register int i,u,v,opt,val;
for(i=1;i<n;++i)
u=read(),v=read(),
add(u,v),add(v,u);
for(i=1;i<=n;++i) V[i]=read();
decomposition::Main();
build(1,1,n);
root=read();
while(m--)
{
opt=read();
switch(opt)
{
case 1:
root=read();
break;
case 2:
u=read(),v=read(),val=read();
get_modify(u,v,val);
break;
case 3:
u=read();
print(get_ans(u));puts("");
break;
}
}
return 0;
}