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; }