传送门
题意简述:
给一棵
n
n
n个点的树,树上每个点表示一个情报员,一共有
m
m
m天,每天会派发以下两种任务中的一个任务:
1.搜集情报:指派T号情报员搜集情报
2.传递情报:将一条情报从X号情报员传递给Y号情报员
一个情报员在搜集情报之前危险度为
0
0
0,从开始搜集的第二天起每天危险度加一。
每条情报都有一个风险控制值C,现在要求对于每个任务,参与传递的情报员有多少个,其中对危险度大于这条情报的
C
C
C值的情报员有多少个。
思路:
对于第一个问题显然求
l
c
a
lca
lca就完了,对于第二个问题我们可以离线排序,我们不妨令一个情报员开始搜集情报的时间和每条情报的出现时间都记作
v
v
v。
那么一个点
i
i
i可能对一条情报
j
j
j产生贡献当且仅当
v
i
<
v
j
−
c
j
v_i<v_j-c_j
vi<vj−cj,因此我们把情报员按照
v
v
v排序,把情报按照
v
−
c
v-c
v−c排序。
然后用一个归并排序来决定修改查询的顺序,这样只用一个树链剖分维护一下就完了。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int N=2e5+5;
int n,m,siz[N],hson[N],top[N],fa[N],dep[N],num[N],ans[N],len[N],tot=0;
bool vis[N];
vector<int>e[N];
namespace Bit{
int bit[N];
inline int lowbit(const int&x){return x&-x;}
inline void update(int x,int v){for(ri i=x;i<=n;i+=lowbit(i))bit[i]+=v;}
inline int query(int x){int ret=0;for(ri i=x;i;i^=lowbit(i))ret+=bit[i];return ret;}
}
void dfs1(int p){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
fa[v=e[p][i]]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
void dfs2(int p,int tp){
top[p]=tp,num[p]=++tot;
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i])!=hson[p])dfs2(v,v);
}
inline int lca(int x,int y){
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline int query(int x,int y){
int ret=0;
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret+=Bit::query(num[x])-Bit::query(num[top[x]]-1),x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
return ret+Bit::query(num[x])-Bit::query(num[y]-1);
}
struct Upd{int x,v;friend inline bool operator<(const Upd&a,const Upd&b){return a.v<b.v;}}upd[N];
struct Qry{int x,y,id,v;friend inline bool operator<(const Qry&a,const Qry&b){return a.v<b.v;}}qry[N];
int main(){
n=read();
int rt,t1=0,t2=0,p1=1,p2=1;
for(ri i=1;i<=n;++i)if(!(fa[i]=read()))rt=i;else e[fa[i]].push_back(i);
dfs1(rt),dfs2(rt,rt);
m=read();
for(ri op,x,y,v,i=1;i<=m;++i){
op=read();
if(op==2)upd[++t1]=(Upd){read(),i};
else{
x=read(),y=read(),v=read(),++t2;
qry[t2]=(Qry){x,y,t2,i-v-1};
len[t2]=dep[x]+dep[y]-dep[lca(x,y)]*2+1;
}
}
sort(upd+1,upd+t1+1),sort(qry+1,qry+t2+1);
while(p1<=t1&&p2<=t2){
if(upd[p1].v<=qry[p2].v){if(!vis[upd[p1].x])Bit::update(num[upd[p1].x],1),vis[upd[p1].x]=1;++p1;}
else ans[qry[p2].id]=query(qry[p2].x,qry[p2].y),++p2;
}
while(p2<=t2)ans[qry[p2].id]=query(qry[p2].x,qry[p2].y),++p2;
for(ri i=1;i<=t2;++i)cout<<len[i]<<' '<<ans[i]<<'\n';
return 0;
}