bzoj4756[Usaco2017 Jan]Promotion Counting 树上主席树

来源:互联网 发布:创维网络电视怎么使用 编辑:程序博客网 时间:2024/05/22 09:03

比较简单的树上主席树,对于整一颗子树,用dfs序把他延伸成序列然后直接查询就好了

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=2e5+5;const int M=N*10;int n,sz,a[N],b[N];int cnt,tot,tim;int in[N],out[N],root[N],sum[M],ls[M],rs[M];int head[N],go[N],next[N],val[N];inline void add(int x,int y){    go[++tot]=y;    next[tot]=head[x];    head[x]=tot;}inline void update(int &x,int l,int r,int pos){    int mid=(l+r)>>1;    sum[++sz]=sum[x]+1;    ls[sz]=ls[x];    rs[sz]=rs[x],x=sz;    if (l==r)return;    if (pos<=mid)update(ls[x],l,mid,pos);    else update(rs[x],mid+1,r,pos);}inline int query(int l1,int r1,int l,int r,int a,int b){    int mid=(l+r)>>1;    int ans=0;    if (a<=l&&r<=b)return sum[r1]-sum[l1];    if (a<=mid)ans+=query(ls[l1],ls[r1],l,mid,a,b);    if (mid+1<=b)ans+=query(rs[l1],rs[r1],mid+1,r,a,b);    return ans;}inline void dfs(int x){    in[x]=++tim;    root[in[x]]=root[in[x]-1];    update(root[in[x]],1,cnt,a[x]);    for(int i=head[x];i;i=next[i])    {        dfs(go[i]);    }    out[x]=tim;}int main(){    scanf("%d",&n);    fo(i,1,n)    {        scanf("%d",&a[i]);        b[++cnt]=a[i];    }    sort(b+1,b+cnt+1);    cnt=unique(b+1,b+cnt+1)-b-1;    fo(i,1,n)a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;    fo(i,2,n)    {        int fa;        scanf("%d",&fa);        add(fa,i);    }    dfs(1);    fo(i,1,n)    {        int ans=query(root[in[i]-1],root[out[i]],1,cnt,a[i]+1,cnt);        printf("%d\n",ans);    }}
阅读全文
0 0