其他分享
首页 > 其他分享> > [Usaco2017 Jan]Promotion Counting

[Usaco2017 Jan]Promotion Counting

作者:互联网

n只奶牛构成了一个树形的公司,每个奶牛有一个能力值pi,1号奶牛为树根。
问对于每个奶牛来说,它的子树中有几个能力值比它大的。
Input
n,表示有几只奶牛 n<=100000
接下来n行为1-n号奶牛的能力值pi
接下来n-1行为2-n号奶牛的经理(树中的父亲)
Output
共n行,每行输出奶牛i的下属中有几个能力值比i大
Sample Input
5
804289384
846930887
681692778
714636916
957747794
1
1
2
3
Sample Output
2
0
1
0
0

 

//针对所有点先分别建立权值线段树,然后进行线段树的合并 
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
int n,cnt;
int pre[maxn],son[maxn],now[maxn];
int val[maxn],rt[maxn],ans[maxn],tmp[maxn];
 
int read() 
{
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
 
struct segment_tree 
{
     
    int tot;
    int siz[maxn*20],ls[maxn*20],rs[maxn*20];
     
    void update(int p) 
	{
         siz[p]=siz[ls[p]]+siz[rs[p]];
    }
 
    void build(int &p,int l,int r,int v) 
    //T.build(rt[i],1,n,val[i]);
	{
    if(!p)
	    p=++tot;
    if(l==r) 
	{
        siz[p]=1;//第p个结点的大小为1 
        return;
    }
    int mid=(l+r)>>1;
    if(v<=mid)
	    build(ls[p],l,mid,v);
    else 
	    build(rs[p],mid+1,r,v);
    update(p);
}
 
int merge(int x,int y) 
{
    if(x==0||y==0)
	   return x+y;
    ls[x]=merge(ls[x],ls[y]);
    rs[x]=merge(rs[x],rs[y]);
    update(x);
	return x;
}
 
int find(int p,int l,int r,int v) 
{
    if(p==0)
	    return 0;
    int mid=(l+r)>>1;
    if(v<=mid)
	   return  find(ls[p],l,mid,v);
    return siz[ls[p]]+find(rs[p],mid+1,r,v);
}
}T;
 
void add(int a,int b) 
{
    pre[++cnt]=now[a];
    now[a]=cnt,son[cnt]=b;
}
 
int dfs(int u) 
{
    int root=0;
    for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
         root=T.merge(root,dfs(v)); 
	//将以u为父亲的所有点的线段树进行合并,合并完了后再来统计 
    ans[u]=T.siz[root]-T.find(root,1,n,val[u]);
	//用总结点个数减去小于等于val[u]的 
    return T.merge(root,rt[u]);
	//将u与上面形成的线段树再合并

}
 
int main() 
{
    n=read();
    for(int i=1;i<=n;i++)
         tmp[i]=val[i]=read();
    sort(tmp+1,tmp+n+1);
    int sum=unique(tmp+1,tmp+n+1)-tmp-1;
    for(int i=1;i<=n;i++) 
	{
         val[i]=lower_bound(tmp+1,tmp+sum+1,val[i])-tmp;
         T.build(rt[i],1,n,val[i]);
		 //先针对每个点建立一个线段树出来 
    }
    for(int i=2;i<=n;i++) 
	{
           int f=read();
           add(f,i);//i与其父亲f连边 
    }
    dfs(1);
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}
 

  

标签:Usaco2017,ch,int,Jan,include,maxn,Promotion,奶牛,getchar
来源: https://www.cnblogs.com/cutemush/p/11835761.html