1. 程式人生 > >【USACO 2017 Jan】Promotion Counting

【USACO 2017 Jan】Promotion Counting

【題目】

Description

The cows have once again tried to form a startup company, failing to remember from past experience that cows make terrible managers!The cows, conveniently numbered 1…N (1≤N≤100,000), organize the company as a tree, with cow 1 as the president (the root of the tree). Each cow except the president has a single manager (its “parent” in the tree). Each cow i has a distinct proficiency rating,p(i), which describes how good she is at her job. If cow i is an ancestor (e.g., a manager of a manager of a manager) of cow j, then we say j is a subordinate of i.

Unfortunately, the cows find that it is often the case that a manager has less proficiency than several of her subordinates, in which case the manager should consider promoting some of her subordinates. Your task is to help the cows figure out when this is happening. For each cow i in the company, please count the number of subordinates j where p(j)>p(i).

Input

The first line of input contains N

The next N lines of input contain the proficiency ratings p(1)…p(N) for the cows. Each is a distinct integer in the range 1…1,000,000,000

The next N-1 lines describe the manager (parent) for cows 2…N

Recall that cow 1 has no manager, being the president.

Output

Please print N lines of output. The ith line of output should tell the number of subordinates of cow i with higher proficiency than cow i.

Sample Input

5 804289384 846930887 681692778 714636916 957747794 1 1 2 3

Sample Output

2 0 1 0 0

【分析】

題目大意:給出一棵樹(根為 11),每個點有點權,對於每個點,詢問它子樹中點權比它大的點的個數

其實可以把這道題當成線段樹合併入門題來做

首先把點權離散化,把所有的點都先單獨建一顆權值線段樹

然後從根開始 dfsdfs,一邊 dfsdfs 一邊合併線段樹,不斷合併上去,最後求答案就行了

【程式碼】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
int n,m,t,tot;
int first[N],v[N],nxt[N];
int a[N],ans[N],val[N],root[N],size[N*40],lc[N*40],rc[N*40];
void add(int x,int y)
{
	t++;
	nxt[t]=first[x];
	first[x]=t;
	v[t]=y;
}
void build(int &root,int l,int r,int val)
{
	root=++tot;
	size[root]=1;
	if(l==r)  return;
	int mid=(l+r)>>1;
	if(val<=mid)  build(lc[root],l,mid,val);
	else  build(rc[root],mid+1,r,val);
}
int Merge(int x,int y)
{
	if(!x)  return y;
	if(!y)  return x;
	size[x]+=size[y];
	lc[x]=Merge(lc[x],lc[y]);
	rc[x]=Merge(rc[x],rc[y]);
	return x;
}
int calc(int root,int l,int r,int x,int y)
{
	if(l>=x&&r<=y)
	  return size[root];
	int ans=0,mid=(l+r)>>1;
	if(x<=mid)  ans+=calc(lc[root],l,mid,x,y);
	if(y>mid)  ans+=calc(rc[root],mid+1,r,x,y);
	return ans;
}
void dfs(int x)
{
	int i,j;
	for(i=first[x];i;i=nxt[i])
	{
		j=v[i],dfs(j);
		root[x]=Merge(root[x],root[j]);
	}
	ans[x]=calc(root[x],1,m,val[x]+1,m);
}
int main()
{
	int x,i;
	scanf("%d",&n);
	for(i=1;i<=n;++i)  scanf("%d",&a[i]),val[i]=a[i];
	for(i=2;i<=n;++i)  scanf("%d",&x),add(x,i);
	sort(a+1,a+n+1),m=unique(a+1,a+n+1)-(a+1);
	for(i=1;i<=n;++i)
	{
		val[i]=lower_bound(a+1,a+m+1,val[i])-a;
		build(root[i],1,m,val[i]);
	}
	dfs(1);
	for(i=1;i<=n;++i)
	  printf("%d\n",ans[i]);
	return 0;
}