遥远的国度 bzoj3083
分析:
这个题一看就是裸的树剖...
唯一值得考虑的就是它的根一直在变化,我们可以这样想,如果假根在这个点的子树外,那么直接将这个点的子树作为答案区间,如果在子树内,则相对复杂,我们假设son为root所在的节点x的儿子的子树内的儿子编号,那么答案就是min(1到idx[son]-1,idx[son]+siz[son]到n),而如何求son...(这题数据水,暴力可过)详情请见代码,是树剖的一种应用。
本人wa了一天(没有考虑到ro0t==x的请况),在这种情况下,直接查1-n的最小值就行
附上代码:
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <cstdlib> #include <queue> #include <iostream> using namespace std; #define N 300005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node { int to,next; }e[N<<1]; int head[N],cnt,dep[N],fa[N],rot,anc[N],n,Q,siz[N],son[N],idx[N],tims,p[N]; long long minn[N<<2],cov[N<<2],a[N]; void add(int x,int y) { e[cnt].to=y; e[cnt].next=head[x]; head[x]=cnt++; return ; } void dfs1(int x,int from) { fa[x]=from,dep[x]=dep[from]+1,siz[x]=1; for(int i=head[x];i!=-1;i=e[i].next) { int to1=e[i].to; if(to1!=from) { dfs1(to1,x); siz[x]+=siz[to1]; if(siz[son[x]]<siz[to1])son[x]=to1; } } } void dfs2(int x,int top) { anc[x]=top;idx[x]=++tims;p[tims]=x; if(son[x])dfs2(son[x],top); for(int i=head[x];i!=-1;i=e[i].next) { int to1=e[i].to; if(to1!=fa[x]&&to1!=son[x])dfs2(to1,to1); } } void PushUp(int rt) { minn[rt]=min(minn[rt<<1],minn[rt<<1|1]); } void PushDown(int rt) { if(cov[rt]) { cov[rt<<1]=cov[rt]; minn[rt<<1]=cov[rt]; cov[rt<<1|1]=cov[rt]; minn[rt<<1|1]=cov[rt]; cov[rt]=0; } } void build(int l,int r,int rt) { if(l==r) { minn[rt]=a[p[l]]; return ; } int m=(l+r)>>1; build(lson); build(rson); PushUp(rt); } void Update(int L,int R,long long c,int l,int r,int rt) { if(L<=l&&r<=R){cov[rt]=minn[rt]=c;return ;} PushDown(rt);int m=(l+r)>>1; if(m>=L)Update(L,R,c,lson); if(m<R)Update(L,R,c,rson); PushUp(rt); } long long query(int L,int R,int l,int r,int rt) { if(L>R)return 1ll<<32; if(L<=l&&r<=R)return minn[rt]; PushDown(rt);int m=(l+r)>>1;long long ret=1ll<<32; if(m>=L)ret=min(query(L,R,lson),ret); if(m<R)ret=min(query(L,R,rson),ret); PushUp(rt); return ret; } void get_lca_Update(int x,int y,long long c) { while(anc[x]!=anc[y]) { if(dep[anc[x]]<dep[anc[y]])swap(x,y); Update(idx[anc[x]],idx[x],c,1,n,1); x=fa[anc[x]]; } if(dep[x]>dep[y])swap(x,y); Update(idx[x],idx[y],c,1,n,1); } int get_lca(int x,int y) { if(anc[x]==anc[y])return son[y]; while(anc[fa[anc[x]]]!=anc[y]) { x=fa[anc[x]]; } if(fa[anc[x]]!=y)return son[y]; return anc[x]; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d",&n,&Q); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=n;i++)scanf("%lld",&a[i]); dfs1(1,0); dfs2(1,1); build(1,n,1); scanf("%d",&rot); while(Q--) { int op,x,y;long long z; scanf("%d%d",&op,&x); //for(int i=1;i<=n;i++)printf("%d ",query(idx[i],idx[i],1,n,1)); // puts(""); if(op==3) { if(rot==x)printf("%lld\n",query(1,n,1,n,1)); else if(idx[rot]>=idx[x]+siz[x]||idx[rot]<=idx[x]) printf("%lld\n",query(idx[x],idx[x]+siz[x]-1,1,n,1)); else { int t=get_lca(rot,x); printf("%lld\n",min(query(1,idx[t]-1,1,n,1),query(idx[t]+siz[t]-1,n,1,n,1))); } }else if(op==2) { scanf("%d%lld",&y,&z); // int a=query(idx[x],idx[x],1,n,1),b=query(idx[y],idx[y],1,n,1); get_lca_Update(x,y,z); // Update(idx[x],idx[x],a,1,n,1),Update(idx[y],idx[y],b,1,n,1); }else rot=x; } return 0; }