zoukankan      html  css  js  c++  java
  • 线段树合并 || 树状数组 || 离散化 || BZOJ 4756: [Usaco2017 Jan]Promotion Counting || Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数

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

    题解:这是一道万能题,树状数组 || 主席树 || 线段树合并 || 莫队套分块 || 线段树 都可以写。。记得离散化

    线段树合并版:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxn=(1e5)+50;
     7 int N,num_edge=0,edge_head[maxn],W[maxn],lsh_cnt=0,num_treenode=0;
     8 int root[maxn],ans[maxn],u;
     9 struct A_{int id,data;}A[maxn];
    10 inline bool cmp(const A_&a,const A_&b){return a.data<b.data;}
    11 struct Edge{int to,nx;}edge[maxn];
    12 inline void Add_edge(int from,int to){
    13     edge[++num_edge].nx=edge_head[from];
    14     edge[num_edge].to=to;
    15     edge_head[from]=num_edge;
    16     return;
    17 }
    18 struct Tree{int lc,rc,l,r,cnt;}t[maxn*20];
    19 inline void Build(int x,int l,int r,int q){
    20     t[x].l=l;t[x].r=r;int mid=(l+r)>>1;
    21     if(l==r&&l==q){
    22         t[x].cnt=1;
    23         return;
    24     }
    25     if(q<=mid)Build(t[x].lc=++num_treenode,l,mid,q);
    26     else Build(t[x].rc=++num_treenode,mid+1,r,q);
    27     t[x].cnt=t[t[x].lc].cnt+t[t[x].rc].cnt;
    28     return;
    29 }
    30 inline int Merge(int u,int v){
    31     if(!u)return v;
    32     if(!v)return u;
    33     int l=t[u].l,r=t[u].r;
    34     if(l==r){
    35         t[u].cnt+=t[v].cnt;
    36         return u;
    37     }
    38     t[u].lc=Merge(t[u].lc,t[v].lc);
    39     t[u].rc=Merge(t[u].rc,t[v].rc);
    40     t[u].cnt=t[t[u].lc].cnt+t[t[u].rc].cnt;
    41     return u;
    42 }
    43 inline void Query(int g,int x,int ql,int qr){
    44     int l=t[x].l,r=t[x].r,mid=(l+r)>>1,lc=t[x].lc,rc=t[x].rc;
    45     if(x==0)return;
    46     if(ql<=l&&r<=qr){
    47         ans[g]+=t[x].cnt;
    48         return;
    49     }
    50     if(ql<=mid)Query(g,lc,ql,qr);
    51     if(qr>mid) Query(g,rc,ql,qr);
    52     return;
    53 }
    54 inline void Dfs(int x){
    55     for(int i=edge_head[x];i;i=edge[i].nx){
    56         int y=edge[i].to;
    57         Dfs(y);
    58         root[x]=Merge(root[x],root[y]);
    59     }
    60     if(W[x]+1>lsh_cnt)ans[x]=0;
    61     else Query(x,root[x],W[x]+1,lsh_cnt);
    62     return;
    63 }
    64 int main(){
    65     scanf("%d",&N);
    66     for(int i=1;i<=N;i++){
    67         scanf("%d",&A[i].data);
    68         A[i].id=i;
    69     }
    70     sort(A+1,A+N+1,cmp);
    71     W[A[1].id]=++lsh_cnt;
    72     for(int i=2;i<=N;i++)
    73         if(A[i].data!=A[i-1].data)W[A[i].id]=++lsh_cnt;
    74         else W[A[i].id]=lsh_cnt;
    75     for(int i=2;i<=N;i++){
    76         scanf("%d",&u);
    77         Add_edge(u,i);
    78     }
    79     for(int i=1;i<=N;i++)Build(root[i]=++num_treenode,1,lsh_cnt+5,W[i]);
    80     Dfs(1);
    81     for(int i=1;i<=N;i++)printf("%d
    ",ans[i]);
    82     return 0;
    83 }

    树状数组版:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define ll long long
     6 #define re register
     7 using namespace std;
     8 inline int rd(){
     9     int x=0;char c=getchar();
    10     while(c<'0'||c>'9')c=getchar();
    11     while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    12     return x;
    13 }
    14 const int maxn=1e5;
    15 int N,P[maxn+5],cnt=0,num_edge=0,edge_head[maxn+5],F,C[maxn+5];
    16 ll ans[maxn+5];
    17 struct Edge{
    18     int to,nx;
    19 }edge[maxn+5];
    20 struct Node{
    21     int x,id;
    22 }A[maxn+50];
    23 inline bool cmp(const Node&a,const Node&b){
    24     if(a.x<b.x)return 1;
    25     return 0;
    26 }
    27 inline int Find(int x){
    28     re ll ans=0;
    29     for(;x<=cnt;x+=x&(-x))ans+=C[x];
    30     return ans;
    31 }
    32 inline void Update(int x){
    33     for(;x>0;x-=x&(-x))C[x]++;
    34     return;
    35 }
    36 inline void Dfs(int x){
    37     ans[x]-=Find(P[x]);
    38     for(re int i=edge_head[x];i;i=edge[i].nx) Dfs(edge[i].to);     
    39     ans[x]+=Find(P[x]);
    40     Update(P[x]);
    41     return;
    42 }
    43 int main(){
    44     N=rd();
    45     for(re int i=1;i<=N;i++){
    46         A[i].x=rd();
    47         A[i].id=i;
    48     }
    49     sort(A+1,A+N+1,cmp);
    50     for(re int i=1;i<=N;i++){
    51         if(i==1||A[i].x!=A[i-1].x)cnt++;
    52         P[A[i].id]=cnt;
    53     }
    54     for(re int i=2;i<=N;i++){
    55         scanf("%d",&F);
    56         edge[++num_edge].nx=edge_head[F];
    57            edge[num_edge].to=i;
    58         edge_head[F]=num_edge;
    59     }
    60     Dfs(1);
    61     for(re int i=1;i<=N;i++)printf("%lld
    ",ans[i]);
    62     return 0;
    63 }

    By:AlenaNuna

  • 相关阅读:
    array与xml转换实现(转)
    设计模式之: 策略模式
    设计模式之: 代理模式
    设计模式之: 状态模式
    dedecms分页
    dedecms导出csv文件
    假如项目中使用到了多 表查询,怎么办?
    git忽略某个文件夹
    git忽略某个文件
    无极限分类
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/10525858.html
Copyright © 2011-2022 走看看