zoukankan      html  css  js  c++  java
  • [USACO17JAN]Promotion Counting晋升者计数

    题目描述

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

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

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

    输入输出格式

    输入格式:

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    5
    804289384
    846930887
    681692778
    714636916
    957747794
    1
    1
    2
    3
    输出样例#1:
    2
    0
    1
    0
    0
    树上的树状数组或线段树
    维护按后序遍历树时比当前点值大的数量
    但是遍历到一个点时,维护的数量可能包含了他的兄弟,祖先
    所以求出每个点的答案之前,记录出值pre,在遍历子树,加入树状数组,再求出值ans[x]
    ans[x]=ans[x]-pre
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 struct Messi
     7 {
     8     int next,to;
     9 } edge[200001];
    10 int c[400001];
    11 int n,num,head[100001],a[100001],id[100001],ans[100001],p[100001];
    12 void add(int u,int v)
    13 {
    14     num++;
    15     edge[num].next=head[u];
    16     head[u]=num;
    17     edge[num].to=v;
    18 }
    19 int binary(int x)
    20 {
    21     int l=1,r=n,mid;
    22     while(l<=r)
    23     {
    24         mid=(l+r)>>1;
    25         if(a[mid]==x)return mid;
    26         if(a[mid]>x)r=mid-1;
    27         else l=mid+1;
    28     }
    29     return -1;
    30 }
    31 int getsum(int rt,int l,int r,int L,int R)
    32 {
    33     if (l>=L&&r<=R)
    34     {
    35         return c[rt];
    36     }
    37      int mid=(l+r)/2;
    38      int x=0;
    39      if (L<=mid)
    40       x+=getsum(rt*2,l,mid,L,R);
    41       if (R>mid)
    42       x+=getsum(rt*2+1,mid+1,r,L,R);
    43     return x;
    44 }
    45 void update(int rt,int l,int r,int k)
    46 {
    47     if (l==r)
    48     {
    49         c[rt]=1;
    50      return;
    51     }
    52      int mid=(l+r)/2;
    53       if (k<=mid)
    54        update(rt*2,l,mid,k);
    55        else update(rt*2+1,mid+1,r,k);
    56   c[rt]=c[rt*2]+c[rt*2+1];
    57 }
    58 void dfs(int x)
    59 {int i;
    60     int tmp=getsum(1,1,n,id[x]+1,n);
    61     for (i=head[x];i;i=edge[i].next)
    62     {
    63         dfs(edge[i].to);
    64     }
    65      ans[x]=getsum(1,1,n,id[x]+1,n)-tmp;
    66     update(1,1,n,id[x]);
    67 }
    68 int main()
    69 {int i,x;
    70     cin>>n;
    71     for (i=1; i<=n; i++)
    72     {
    73         scanf("%d",&p[i]);
    74         a[i]=p[i];
    75     }
    76     sort(a+1,a+n+1);
    77     for (i=1; i<=n; i++)
    78         id[i]=binary(p[i]);
    79     for (i=2; i<=n; i++)
    80     {
    81         scanf("%d",&x);
    82         add(x,i);
    83     }
    84      dfs(1);
    85      for (i=1;i<=n;i++)
    86      printf("%d
    ",ans[i]);
    87 }
  • 相关阅读:
    Effective C++ 读书笔记(3544):继承关系与面向对象设计
    《全景探秘游戏设计艺术》读后感之引子
    Effective C++ 读书笔记(1117):构造析构和赋值函数
    Effective C++ 读书笔记(2934):类与函数之实现
    Unity中使用PersistentDataPath加载文件
    打开本地【C】【D】【E】驱动器时候提示 X:\ 找不到应用程序
    C#进制转换
    在VS里编辑unity代码调用系统方法不显示中文注释或英文注释
    Spreadsheet说明
    C#中删除控件的事件的方法类.
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7365414.html
Copyright © 2011-2022 走看看