%%%神仙线段树合并
本来想练练线段树合并的,但是看了看题就树上差分秒切了
考虑到我们维护一个权值为下标的树状数组
每次一个点就这个点
每到一个点先记录一下目前比他大的点有多少个
完他的儿子后再查询一下现在比他大的点有多少个
相减就是答案了
#include<bits/stdc++.h>
using namespace std;
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<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=100005;
int tr[N],a[N],b[N],num,adj[N],ans[N],n,cnt,nxt[N<<1],to[N<<1];
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
inline void init(){
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+num+1,a[i])-b;
}
inline int lowbit(int x){
return (x&(-x));
}
inline void update(int pos){
for(;pos<=n;pos+=lowbit(pos))tr[pos]+=1;
}
inline int query(int pos,int res=0){
for(;pos;pos-=lowbit(pos))res+=tr[pos];
return res;
}
void dfs(int u,int fa){
update(a[u]);
int pre=query(num)-query(a[u]);
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa)continue;
dfs(v,u);
}
int now=query(num)-query(a[u]);
ans[u]=now-pre;
}
int main(){
n=read();
for(int i=1;i<=n;i++)a[i]=b[i]=read();
init();
for(int i=2;i<=n;i++){
int f=read();addedge(f,i),addedge(i,f);
}
dfs(1,0);
for(int i=1;i<=n;i++)cout<<ans[i]<<'
';
}