洛 谷 P 3605 [ U S A C O 17 J A N ] P r o m o t i o n C o u n t i n g 晋 升 者 计 数 \color{#00F}{洛谷\ P3605\ [USACO17JAN]Promotion\ Counting晋升者计数} 洛谷 P3605 [USACO17JAN]Promotion Counting晋升者计数
T
i
m
e
L
i
m
i
t
:
1.00
S
\color{green}{Time\ Limit: 1.00S}
Time Limit:1.00S
M
e
m
o
r
y
L
i
m
i
t
:
125.00
M
B
\color{green}{Memory\ Limit: 125.00MB}
Memory Limit:125.00MB
P
r
o
b
l
e
m
D
e
s
c
r
i
p
t
i
o
n
\color{blue}{Problem\ Description}
Problem Description
洛谷 P3605 [USACO17JAN]Promotion Counting晋升者计数
奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训–牛是可怕的管理者!
为了方便,把奶牛从 1 ⋯ N ( 1 ≤ N ≤ 100 , 000 ) 1\cdots N(1\leq N\leq100,000) 1⋯N(1≤N≤100,000) 编号,把公司组织成一棵树, 1 1 1 号奶牛作为总裁(这棵树的根节点)。除了总裁以外的每头奶牛都有一个单独的上司(它在树上的 “双亲结点”)。所有的第 i i i 头牛都有一个不同的能力指数 p ( i ) p(i) p(i),描述了她对其工作的擅长程度。如果奶牛 i i i 是奶牛 j j j 的祖先节点(例如,上司的上司的上司),那么我们我们把奶牛 j j j 叫做 i i i 的下属。
不幸地是,奶牛们发现经常发生一个上司比她的一些下属能力低的情况,在这种情况下,上司应当考虑晋升她的一些下属。你的任务是帮助奶牛弄清楚这是什么时候发生的。简而言之,对于公司的中的每一头奶牛 i i i,请计算其下属 j j j 的数量满足 p ( j ) > p ( i ) p(j) > p(i) p(j)>p(i)。
I
n
p
u
t
\color{blue}{Input}
Input
输入的第一行包括一个整数
N
N
N。
接下来的 N N N行包括奶牛们的能力指数 p ( 1 ) ⋯ p ( N ) p(1) \cdots p(N) p(1)⋯p(N) . 保证所有数互不相同,在区间 1 ⋯ 1 0 9 1\cdots 10^9 1⋯109 之间。
接下来的 N − 1 N-1 N−1 行描述了奶牛 2 ⋯ N 2 \cdots N 2⋯N 的上司(双亲节点)的编号。再次提醒, 1 1 1 号奶牛作为总裁,没有上司。
O
u
t
p
u
t
\color{blue}{Output}
Output
输出包括
N
N
N 行。输出的第
i
i
i 行应当给出有多少奶牛
i
i
i 的下属比奶牛
i
i
i 能力高。
S
a
m
p
l
e
I
n
p
u
t
\color{blue}{Sample\ Input}
Sample Input
5
804289384
846930887
681692778
714636916
957747794
1
1
2
3
S
a
m
p
l
e
O
u
t
p
u
t
\color{blue}{Sample \ Output}
Sample Output
2
0
1
0
0
先对权值离散化,然后对于每一个节点,我们需要统计它的子树中比它大的节点的个数。所以为了方便统计,离散化可以大的在前。
然后建一棵权值树状数组,在递归子树之前先把答案减掉,递归完子树后再把新的答案加回来,然后修改权值树状数组。
代码实现如下:
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100005;
int n;
int a[MAXN],sum[MAXN],ans[MAXN];
vector <int> ve;
int esize=0;
int head[MAXN];
struct EDGE
{
int u,v;
int next;
}edge[MAXN<<1];
inline int read()
{
int X=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+(ch^'0'); ch=getchar();}
return X*f;
}
inline void addedge(int u,int v)
{
edge[esize].u=u;
edge[esize].v=v;
edge[esize].next=head[u];
head[u]=esize++;
}
inline int lowbit(int x)
{
return x&(-x);
}
inline void add(int p,int x)
{
while(p<=n) sum[p]+=x,p+=lowbit(p);
}
inline int query(int p)
{
int res=0;
while(p)
res+=sum[p],p-=lowbit(p);
return res;
}
void dfs(int u)
{
ans[u]-=query(a[u]);
for(int i=head[u];~i;i=edge[i].next)
dfs(edge[i].v);
ans[u]+=query(a[u]);
add(a[u],1);
}
int main()
{
// freopen("input.txt","r",stdin);
memset(head,-1,sizeof(head));
n=read();
for(int i=1;i<=n;++i)
a[i]=read(),ve.push_back(a[i]);
sort(ve.begin(),ve.end());
ve.erase(unique(ve.begin(),ve.end()),ve.end());
for(int i=1;i<=n;++i)
a[i]=n-(lower_bound(ve.begin(),ve.end(),a[i])-ve.begin()+1)+1;
for(int i=2;i<=n;++i)
{
int u=read();
addedge(u,i);
}
dfs(1);
for(int i=1;i<=n;++i)
printf("%d\n",ans[i]);
return 0;
}