对与每一个时刻用主席树维护一下 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;
}