【BZOJ4448】【SCOI2015】—情报传递(主席树)
相当于求路径上小于的值的数量
直接上主席树,带修
发现后面的修改是不可能对前面的询问有影响
离线先把所有修改了
建树上主席树
每次找区间求一波就可以了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=200005,Log=22;
int n,q,val[N];
namespace Presi_Tree{
int siz[N*Log],tot,lc[N*Log],rc[N*Log],rt[N];
#define mid ((l+r)>>1)
void ins(int &u,int r1,int l,int r,int k){
u=++tot,siz[u]=siz[r1]+1,lc[u]=lc[r1],rc[u]=rc[r1];
if(l==r)return;
if(k<=mid)ins(lc[u],lc[r1],l,mid,k);
else ins(rc[u],rc[r1],mid+1,r,k);
}
inline void insert(int p,int pre,int k){ins(rt[p],rt[pre],1,q,k);}
int qry(int r1,int r2,int l,int r,int k){
if(l==r)return siz[r2]-siz[r1];
if(k<=mid)return qry(lc[r1],lc[r2],l,mid,k);
else return siz[lc[r2]]-siz[lc[r1]]+qry(rc[r1],rc[r2],mid+1,r,k);
}
inline int query(int l,int r,int k){if(k<=0)return 0;return qry(rt[l],rt[r],1,q,k);}
}
using namespace Presi_Tree;
namespace SLPF{
int root,dep[N],fa[N],top[N],siz[N],son[N];
vector<int> e[N];
inline void add(int u,int v){
e[u].pb(v);
}
void dfs1(int u){
siz[u]=1,insert(u,fa[u],val[u]);
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
dep[v]=dep[u]+1;
dfs1(v),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
inline int Lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]>dep[v]?v:u;
}
}
using namespace SLPF;
struct ask{
int op,x,y,c;
}p[N];
inline void chemn(int &a,int b){
a=a>b?b:a;
}
int main(){
n=read();
for(int i=1;i<=n;i++){
fa[i]=read();
if(!fa[i])root=i;
else add(fa[i],i);
}
q=read();
for(int i=1;i<=n;i++)val[i]=q;
for(int i=1;i<=q;i++){
p[i].op=read();
if(p[i].op==1){
p[i].x=read(),p[i].y=read(),p[i].c=read();
}
else p[i].x=read(),p[i].y=i,chemn(val[p[i].x],i);
}
dfs1(root),dfs2(root,root);
for(int i=1;i<=q;i++){
if(p[i].op==2)continue;
int res=0,u=p[i].x,v=p[i].y,k=p[i].c;
int lca=Lca(u,v);
cout<<dep[u]+dep[v]-2*dep[lca]+1<<" ";
res+=query(lca,u,i-k-1),res+=query(lca,v,i-k-1);
res+=(val[lca]<=i-k-1);
cout<<res<<'\n';
}
}