USACO2017JanuaryPlatinum Promotion Counting(奶牛升职计数)

来源:互联网 发布:linux 安装 docker 编辑:程序博客网 时间:2024/05/16 01:21

自联赛过后博主的第一份题解

题意:

给你大小为n的一棵树(以1号节点为根节点,形式为告诉你每个点的父亲的编号),
每个节点都有一个能力值,最终计算每个节点的子树中能力值大于它本身的节点有多少个

解题思路:

这道题还是比较水的
我们只需要一遍dfs
先使该点的ans减去还没遍历过他的子树时能力值大于它的节点数
再加上遍历过子树时能力值大于它的节点数
离散一波然后用树状数组维护就行

#include<bits/stdc++.h>using namespace std;#define M 100005int val[M],tmp[M],head[M],sum[M],ans[M],tot,n;struct node{    int to,nxt;}edge[M];void Add(int a,int b){    edge[tot].to=b;edge[tot].nxt=head[a];head[a]=tot++;}int lowbit(int x){    return x&-x;}void add(int x){    while(x){        sum[x]++;        x-=lowbit(x);    }}int read(int x){    int res=0;    while(x<=n){        res+=sum[x];        x+=lowbit(x);    }    return res;}//树状数组查询大于x的数的个数void dfs(int x){    add(val[x]);    ans[x]-=read(val[x]);//未遍历子树    for(int i=head[x];~i;i=edge[i].nxt)        dfs(edge[i].to);    ans[x]+=read(val[x]);//已遍历子树}int main(){    scanf("%d",&n);    memset(head,-1,sizeof(head));    for(int i=1;i<=n;i++){        scanf("%d",&val[i]);        tmp[i]=val[i];    }    sort(tmp+1,tmp+n+1);    for(int i=1;i<=n;i++)val[i]=lower_bound(tmp+1,tmp+n+1,val[i])-tmp;    for(int i=2;i<=n;i++){        int x;        scanf("%d",&x);        Add(x,i);    }    dfs(1);    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);    return 0;}
1 0