洛谷P3605 [USACO17JAN]Promotion Counting晋升者计数

Posted 沐灵_hh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3605 [USACO17JAN]Promotion Counting晋升者计数相关的知识,希望对你有一定的参考价值。

洛谷P3605 [USACO17JAN]Promotion Counting晋升者计数

题目描述

奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者!

为了方便,把奶牛从 $1 \cdots N(1 \leq N \leq 100, 000)$ 编号,把公司组织成一棵树,1 号奶牛作为总裁(这棵树的根节点)。除了总裁以外的每头奶牛都有一个单独的上司(它在树上的 “双亲结点”)。所有的第 $i$ 头牛都有一个不同的能力指数 $p(i)$,描述了她对其工作的擅长程度。如果奶牛 $i$ 是奶牛 $j$ 的祖先节点(例如,上司的上司的上司),那么我们我们把奶牛 $j$ 叫做 $i$ 的下属。

不幸地是,奶牛们发现经常发生一个上司比她的一些下属能力低的情况,在这种情况下,上司应当考虑晋升她的一些下属。你的任务是帮助奶牛弄清楚这是什么时候发生的。简而言之,对于公司的中的每一头奶牛 $i$,请计算其下属 $j$ 的数量满足 $p(j) > p(i)$。

输入输出格式

输入格式:

输入的第一行包括一个整数 $N$。

接下来的 $N$ 行包括奶牛们的能力指数 $p(1) \cdots p(N)$. 保证所有数互不相同,在区间 $1 \cdots 10^9$ 之间。

接下来的 $N-1$ 行描述了奶牛 $2 \cdots N$ 的上司(双亲节点)的编号。再次提醒,1 号奶牛作为总裁,没有上司。

输出格式:

输出包括 $N$ 行。输出的第 $i$ 行应当给出有多少奶牛 $i$ 的下属比奶牛 $i$ 能力高。

输入输出样例

输入样例#1: 复制
5
804289384
846930887
681692778
714636916
957747794
1
1
2
3
输出样例#1: 复制
2
0
1
0
0

说明

感谢@rushcheyo 的翻译

代码

树上的逆序对问题,用树状数组求,还是原来的思路,但要注意去掉不在一个子树上的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100010;
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*10+ch-0;ch=getchar();}
    return x*f;
}
int n,tot,head[N],b[N],c[N],fa[N],ans[N];
struct node{
    int next,to;
}e[N];
struct data{
    int x,id;
    bool operator < (const data &j)const {
        return x<j.x;
    }
}a[N];
inline void ins(int from,int to){
    e[++tot].next=head[from];
    e[tot].to=to; head[from]=tot;
}
inline void update(int x,int val){
    for(;x<=n;x+=x&(-x)) c[x]+=val;
}
inline int query(int x){
    int res=0; for(;x;x-=x&(-x)) res+=c[x];
    return res;
}
void dfs(int x){
    update(b[x],1);
    int last=query(n)-query(b[x]);
    for(int i=head[x];i;i=e[i].next)
    if(e[i].to!=fa[x]) dfs(e[i].to);
    ans[x]=query(n)-query(b[x])-last;
}
int main(){
    n=read();
    for(int i=1;i<=n;++i) a[i].x=read(),a[i].id=i;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;++i) b[a[i].id]=i;
    for(int i=2;i<=n;++i){
        int x=read(); fa[i]=x;
        ins(x,i); 
    }
    dfs(1);
    for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
    return 0;
}
    

 

以上是关于洛谷P3605 [USACO17JAN]Promotion Counting晋升者计数的主要内容,如果未能解决你的问题,请参考以下文章

P3605 [USACO17JAN]Promotion Counting P (dsu+线段树)

P3605 [USACO17JAN]Promotion Counting P (线段树合并)

P3605 [USACO17JAN]Promotion Counting P (线段树合并)

P3605 [USACO17JAN]Promotion Counting P(树状数组)

P3605 [USACO17JAN]Promotion Counting P(树状数组)

题解 P3605 [USACO17JAN]Promotion Counting晋升者计数