洛谷 P3605 [USACO17JAN]Promotion Counting P【线段树合并】
传送门
离散化+线段树合并。
对能力离散化,然后dfs,用线段树合并统计每一颗子树。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N],b[N],cnt,ans[N],rt[N];
int head[N],nxt[N*2],to[N*2],tot;
void add(int u,int v){to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
struct SegTrees{
#define mid (l+r>>1)
int sum[N*50],ls[N*50],rs[N*50],tot;
void upd(int &u,int l,int r,int pos){
if(!u) u=++tot;
if(l==r) {sum[u]++;return;}
if(pos<=mid) upd(ls[u],l,mid,pos);
else upd(rs[u],mid+1,r,pos);
sum[u]=sum[ls[u]]+sum[rs[u]];
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x+y;
if(l==r) {sum[x]+=sum[y];return x;}
ls[x]=merge(ls[x],ls[y],l,mid);
rs[x]=merge(rs[x],rs[y],mid+1,r);
sum[x]=sum[ls[x]]+sum[rs[x]];
return x;
}
int ask(int id,int l,int r,int L,int R){
if(L<=l&&r<=R) return sum[id];
int res=0;
if(L<=mid) res+=ask(ls[id],l,mid,L,R);
if(R>mid) res+=ask(rs[id],mid+1,r,L,R);
return res;
}
#undef mid
}trs;
void dfs(int u,int fa){
trs.upd(rt[u],1,1e5,a[u]);
for(int i=head[u];i;i=nxt[i]){
if(to[i]==fa) continue;
dfs(to[i],u);
rt[u]=trs.merge(rt[u],rt[to[i]],1,1e5);
}
if(a[u]>=1e5) ans[u]=0;
else ans[u]=trs.ask(rt[u],1,1e5,a[u]+1,1e5);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
cnt=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
for(int v=2,u;v<=n;v++){
scanf("%d",&u);
add(u,v);add(v,u);
}
dfs(1,0);
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}