經過分析,設某個點的起始時間爲,當前時間爲,則對答案有貢獻的點需滿足,即
當然把簡單路徑拆成到根節點的四條路徑,那麼修改一個點會對它子樹產生影響,就可以按當前時間建主席樹搞一搞了
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2e5+5;
namespace President_tree{
struct seg{int l,r,sum;}tr[N*50];int cnt=0;
#define ls(k) tr[k].l
#define rs(k) tr[k].r
#define mid (l+r>>1)
inline void ins(int &rt1,int rt2,int l,int r,int ql,int qr){
tr[rt1=++cnt]=tr[rt2];
if(ql<=l && r<=qr){++tr[rt1].sum;return;}
if(ql<=mid) ins(ls(rt1),ls(rt2),l,mid,ql,qr);
if(mid<qr) ins(rs(rt1),rs(rt2),mid+1,r,ql,qr);
}
inline int query(int rt,int l,int r,int pos){
if(!rt) return 0;
if(l==r) return tr[rt].sum;
int res=0;
if(pos<=mid) res+=query(ls(rt),l,mid,pos);
else res+=query(rs(rt),mid+1,r,pos);
return res+tr[rt].sum;
}
}
using namespace President_tree;
int vis[N<<1],nxt[N<<1],head[N],tot=0;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int siz[N],dep[N],hson[N],fa[N];
void dfs1(int v){
siz[v]=1;
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
dep[y]=dep[v]+1;
dfs1(y);
siz[v]+=siz[y];
if(siz[y]>siz[hson[v]]) hson[v]=y;
}
}
int top[N],sign=0,dfn[N];
void dfs2(int v){
dfn[v]=++sign;
top[v]=v==hson[fa[v]]?top[fa[v]]:v;
for(int i=head[v];i;i=nxt[i])
if(!top[vis[i]]) dfs2(vis[i]);
}
inline 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 root,rt[N],pt[N],tim[N];
int n;
inline int get(int Time,int pos){
if(!dfn[pos] || !tim[Time]) return 0;
return query(rt[tim[Time]],1,n,dfn[pos]);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
fa[i]=read();
if(!fa[i]) root=i;
else add(fa[i],i);
}
dep[1]=1;dfs1(root);top[root]=root;dfs2(root);
int m=read();
for(int i=1;i<=m;i++){
tim[i]=tim[i-1];
int op=read();
if(op==2){
int x=read();
if(pt[x]) continue;
++tim[i];pt[x]=1;
ins(rt[tim[i]],rt[tim[i-1]],1,n,dfn[x],dfn[x]+siz[x]-1);
}
else{
int x=read(),y=read(),z=read();
int q=max(i-z-1,0);
int lc=lca(x,y);
cout<<dep[x]+dep[y]-dep[lc]-dep[fa[lc]]<<" ";
cout<<get(q,x)+get(q,y)-get(q,lc)-get(q,fa[lc])<<"\n";
}
}
return 0;
}