线段树合并练习1——P3605 [USACO17JAN]Promotion Counting晋升者计数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Love_mona/article/details/81283681

蒟蒻的垂死挣扎

第一篇当然是模板题啦。

对每一个点开一棵线段树,动态开点,合并的时候同样动态开点总和信息即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#define ll long long
#define MOD 1000000007
#define N 110000
#define RG register

using namespace std;

inline ll read(){
    RG ll x=0,o=1; RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') o=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=((x<<3)+(x<<1))+ch-'0',ch=getchar();
    return x*o;
}

int n,yyb[N],len,p[N],root[N],top,first[N],ans[N];
struct mona { int nxt,en; } s[N<<1];
inline void Insert(int x,int y) { s[++top]=(mona) { first[x],y },first[x]=top; }
struct SegTree {
    int tot,ls[N*80],rs[N*80],num[N*80];
    inline void Build(int l,int r,int &x,int val){
        x=++tot,++num[x]; if(l==r) return ;
        int mid=(l+r)>>1;
        if(val<=mid) Build(l,mid,ls[x],val);
        else Build(mid+1,r,rs[x],val);
    }
    inline int Query(int l,int r,int now,int L,int R){
        if(l>=L&&r<=R) return num[now]; if(L>R) return 0;
        int mid=(l+r)>>1,ans=0;
        if(L<=mid) ans+=Query(l,mid,ls[now],L,R);
        if(R>mid) ans+=Query(mid+1,r,rs[now],L,R);
        return ans;
    }
    inline int Union(int u,int v){
        if(!u||!v) return u+v;
        int t=++tot; num[t]=num[u]+num[v];
        ls[t]=Union(ls[u],ls[v]);
        rs[t]=Union(rs[u],rs[v]);
        return t;
    }
} T;
inline void Orz(){
    sort(yyb+1,yyb+1+len);
    len=unique(yyb+1,yyb+1+len)-yyb-1;
    for(RG int i=1;i<=n;++i) p[i]=lower_bound(yyb+1,yyb+1+len,p[i])-yyb;
}
inline void Dfs(int k,int fa){
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(en==fa) continue ;
        Dfs(en,k),root[k]=T.Union(root[k],root[en]);
    }   ans[k]+=T.Query(1,len,root[k],p[k]+1,len);
}

int main(){
    n=len=read(); for(RG int i=1;i<=n;++i) p[i]=yyb[i]=read();
    Orz(); for(RG int i=1;i<=n;++i) T.Build(1,len,root[i],p[i]);
    for(RG int i=1;i<n;++i){
        int x=read(); Insert(x,i+1),Insert(i+1,x);
    }   Dfs(1,0);
    for(RG int i=1;i<=n;++i) printf("%d\n",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/Love_mona/article/details/81283681
今日推荐