P4216 情报传递 题解
System_Error_ · · 题解
首先进行题意转换,假设当前操作的时间是第
这篇题解就是介绍一下 严谨一点,其实是
不知道为啥题解区里都说是
第
code:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,q,root,sz[N],fa[N],d[N],son[N],rk[N],tp[N],vis[N],tot=0,rt[N],sum[N<<5],ls[N<<5],rs[N<<5],head[N],cnt=0,dfn=0;
struct node {int to,nxt;}e[N];
void add(int u,int v) {e[++cnt]=(node){v,head[u]};head[u]=cnt;}
void dfs1(int u,int pre,int dep) {
int mx=0;
sz[u]=1,fa[u]=pre,d[u]=dep;
for(int i=head[u]; ~i; i=e[i].nxt) {
int v=e[i].to;
if(v==pre) continue;
dfs1(v,u,dep+1);
sz[u]+=sz[v];
if(sz[v]>mx) mx=sz[v],son[u]=v;
}
}
void dfs2(int u,int top) {
rk[u]=++dfn,tp[u]=top;
if(!son[u]) return;
dfs2(son[u],top);
for(int i=head[u]; ~i; i=e[i].nxt) {
int v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
int build(int l,int r) {
int x=++tot;
if(l==r) return x;
int mid=l+r>>1;
ls[x]=build(l,mid);
rs[x]=build(mid+1,r);
return x;
}
int add(int lst,int l,int r,int a) {
int x=++tot;
sum[x]=sum[lst]+1,ls[x]=ls[lst],rs[x]=rs[lst];
if(l==r) return x;
int mid=l+r>>1;
if(a<=mid) ls[x]=add(ls[lst],l,mid,a);
else rs[x]=add(rs[lst],mid+1,r,a);
return x;
}
int query(int l,int r,int x,int y,int id) {
if(l>=x&&r<=y) return sum[id];
if(r<x||l>y) return 0;
int mid=l+r>>1;
return query(l,mid,x,y,ls[id])+query(mid+1,r,x,y,rs[id]);
}
pair<int,int> ask(int x,int y,int id) {
int ans=0;
while(tp[x]!=tp[y]) {
if(d[tp[x]]<d[tp[y]]) swap(x,y);
ans+=query(1,n,rk[tp[x]],rk[x],rt[id]);
x=fa[tp[x]];
}
if(d[x]>d[y]) swap(x,y);
return make_pair(x,ans+query(1,n,rk[x],rk[y],rt[id]));
}
int main() {
cin>>n;
memset(head,-1,sizeof(head));
for(int i=1; i<=n; i++) {
int p;
cin>>p;
if(!p) root=i;
else add(p,i);
}
dfs1(root,0,1);
dfs2(root,root);
rt[0]=build(1,n);
cin>>q;
for(int i=1; i<=q; i++) {
int op;
cin>>op;
if(op==1) {
int x,y,c;
cin>>x>>y>>c;
pair<int,int> p=ask(x,y,max(i-c-1,0));
cout<<d[x]+d[y]-2*d[p.first]+1<<" "<<p.second<<endl;
rt[i]=rt[i-1];
} else {
int t;
cin>>t;
if(!vis[t]) rt[i]=add(rt[i-1],1,n,rk[t]),vis[t]=true;
else rt[i]=rt[i-1];
}
}
}
马蜂丑轻喷。