BZOJ 4448: [Scoi2015]情报传递 DFS序+主席树
对与每一个时刻用主席树维护一下 DFS 序即可.
LCA 的话树剖求解比较快.
code:
#include <cstdio> #include <string> #include <cstring> #include <algorithm> #define N 200006 using namespace std; namespace IO { void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); freopen(out.c_str(),"w",stdout); } }; namespace se { #define lson t[x].ls #define rson t[x].rs struct node { int ls,rs,sum; }t[N*50]; int tot; int newnode() { return ++tot; } void build(int &x,int l,int r) { x=newnode(); if(l==r) return; int mid=(l+r)>>1; build(lson,l,mid),build(rson,mid+1,r); } int update(int pre,int l,int r,int p,int v) { int x=newnode(); t[x]=t[pre]; t[x].sum=t[pre].sum+v; if(l==r) return x; int mid=(l+r)>>1; if(p<=mid) lson=update(t[pre].ls,l,mid,p,v); else rson=update(t[pre].rs,mid+1,r,p,v); return x; } int query(int x,int l,int r,int L,int R) { if(!x) return 0; if(l>=L&&r<=R) return t[x].sum; int re=0,mid=(l+r)>>1; if(L<=mid) re+=query(lson,l,mid,L,R); if(R>mid) re+=query(rson,mid+1,r,L,R); return re; } #undef lson #undef rson }; int n,edges,dfn; int hd[N],to[N],nex[N],st[N],ed[N],dep[N],size[N],son[N],top[N],fa[N],Rt[N]; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs1(int u) { st[u]=++dfn; size[u]=1; for(int i=hd[u];i;i=nex[i]) { dep[to[i]]=dep[u]+1; dfs1(to[i]); size[u]+=size[to[i]]; if(size[to[i]]>size[son[u]]) son[u]=to[i]; } ed[u]=dfn; } void dfs2(int u,int tp) { top[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(v==son[u]) continue; dfs2(v,v); } } int LCA(int x,int y) { while(top[x]!=top[y]) { dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; } return dep[x]<dep[y]?x:y; } int main() { // IO::setIO("input"); int i,j,q,rt=0,tim=0; scanf("%d",&n); for(i=1;i<=n;++i) { int ff; scanf("%d",&ff); fa[i]=ff; if(!ff) rt=i; else add(ff,i); } dfs1(rt); dfs2(rt,rt); se::build(Rt[0],1,n); scanf("%d",&q); for(i=1;i<=q;++i) { int op; tim=i; Rt[tim]=Rt[tim-1]; scanf("%d",&op); if(op==1) { int x,y,c; scanf("%d%d%d",&x,&y,&c); printf("%d ",dep[x]+dep[y]-2*dep[LCA(x,y)]+1); if(c>=tim) printf("0\n"); else { int x1=0,x2=0,x3=0,x4=0,lca=LCA(x,y); x1=se::query(Rt[tim-c-1],1,n,1,st[x]); x2=se::query(Rt[tim-c-1],1,n,1,st[y]); x3=se::query(Rt[tim-c-1],1,n,1,st[lca]); x4=se::query(Rt[tim-c-1],1,n,1,st[fa[lca]]); printf("%d\n",x1+x2-x3-x4); } } else { int t; scanf("%d",&t); Rt[tim]=se::update(Rt[tim],1,n,st[t],1); if(ed[t]<n) Rt[tim]=se::update(Rt[tim],1,n,ed[t]+1,-1); } } return 0; }