• BZOJ4756:[USACO]Promotion Counting(线段树合并)


    Description

    n只奶牛构成了一个树形的公司,每个奶牛有一个能力值pi,1号奶牛为树根。
    问对于每个奶牛来说,它的子树中有几个能力值比它大的。

    Input

    n,表示有几只奶牛 n<=100000
    接下来n行为1-n号奶牛的能力值pi
    接下来n-1行为2-n号奶牛的经理(树中的父亲)

    Output

    共n行,每行输出奶牛i的下属中有几个能力值比i大

    Sample Input

    5
    804289384
    846930887
    681692778
    714636916
    957747794
    1
    1
    2
    3

    Sample Output

    2
    0
    1
    0
    0

    Solution

    线段树合并模板题,$DFS$一遍,然后把儿子的线段树合并到自己身上,查询比自己能力值大的有多少个。

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #define N (100009)
     4 #define INF (1000000000)
     5 using namespace std;
     6 
     7 struct Sgt{int ls,rs,val;}Segt[N<<5];
     8 struct Edge{int to,next;}edge[N<<1];
     9 int n,x,sgt_num,a[N],ans[N],Root[N];
    10 int head[N],num_edge;
    11 
    12 void add(int u,int v)
    13 {
    14     edge[++num_edge].to=v;
    15     edge[num_edge].next=head[u];
    16     head[u]=num_edge;
    17 }
    18 
    19 void Update(int &now,int l,int r,int x)
    20 {
    21     if (!now) now=++sgt_num;
    22     Segt[now].val++;
    23     if (l==r) return;
    24     int mid=(l+r)>>1;
    25     if (x<=mid) Update(Segt[now].ls,l,mid,x);
    26     else Update(Segt[now].rs,mid+1,r,x);
    27 }
    28 
    29 int Query(int now,int l,int r,int l1,int r1)
    30 {
    31     if (l>r1 || r<l1) return 0;
    32     if (l1<=l && r<=r1) return Segt[now].val;
    33     int mid=(l+r)>>1,ls=Segt[now].ls,rs=Segt[now].rs;
    34     return Query(ls,l,mid,l1,r1)+Query(rs,mid+1,r,l1,r1);
    35 }
    36 
    37 void Merge(int &x,int y)
    38 {
    39     if (!x || !y) {x|=y; return;}
    40     Segt[x].val+=Segt[y].val;
    41     Merge(Segt[x].ls,Segt[y].ls);
    42     Merge(Segt[x].rs,Segt[y].rs); 
    43 }
    44 
    45 void DFS(int x,int fa)
    46 {
    47     for (int i=head[x]; i; i=edge[i].next)
    48         if (edge[i].to!=fa)
    49         {
    50             DFS(edge[i].to,x);
    51             Merge(Root[x],Root[edge[i].to]);
    52         }
    53     ans[x]=Query(Root[x],1,INF,a[x]+1,INF);
    54 }
    55 
    56 int main()
    57 {
    58     scanf("%d",&n);
    59     for (int i=1; i<=n; ++i)
    60     {
    61         scanf("%d",&a[i]);
    62         Update(Root[i],1,INF,a[i]);
    63     }
    64     for (int i=2; i<=n; ++i)
    65     {
    66         scanf("%d",&x);
    67         add(i,x); add(x,i);
    68     }
    69     DFS(1,0);
    70     for (int i=1; i<=n; ++i)
    71         printf("%d
    ",ans[i]);
    72 }
  • 相关阅读:
    CSS3 背景
    CSS3 边框
    CSS3中的transform变形
    兼容IE与firefox火狐的回车事件(js与jquery)
    JS相关链接
    JS操作DOM元素属性和方法
    用js给html设置style
    JavaScript数学函数(一)
    [JS] 如何清空file input框 [整理]
    未在本地计算机上注册Microsoft.ACE.OLEDB.12.0提供程序(Oledb)
  • 原文地址:https://www.cnblogs.com/refun/p/10057114.html
Copyright © 2020-2023  润新知