zoukankan      html  css  js  c++  java
  • P3605 [USACO17JAN]Promotion Counting晋升者计数 线段树合并 or 树状数组

    题意:每个点有一个权值    求每个节点的子树中比其权值大的节点数

    线段树合并模板题

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    /////////////////////////////////////
    const int N=1e5+100;
    
    int t[N<<5],b[N],lson[N<<5],rson[N<<5],T[N],pos,head[N],ncnt,n,ans[N],node[N],nn;
    struct Edge{int to,nex;}edge[N<<1];
    void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;}
    void upnode(int x,int l,int r,int &pos)
    {
        if(!pos)pos=++ncnt;
        if(l==r){t[pos]++;return ;}
        int m=(l+r)>>1;
        if(x<=m)upnode(x,l,m,lson[pos]);
        else upnode(x,m+1,r,rson[pos]);
        t[pos]=t[lson[pos]]+t[rson[pos]];
    }
    int qsum(int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)return t[pos];
        int m=(l+r)>>1;int ans=0;
        if(L<=m)ans+=qsum(L,R,l,m,lson[pos]);
        if(R>m)ans+=qsum(L,R,m+1,r,rson[pos]);
        return ans;
    }
    int Merge(int a,int b,int l,int r)
    {
        if(!a)return b;
        if(!b)return a;
        if(l==r)
        {
            t[a]+=t[b];
            return a;
        }
        int m=(l+r)>>1;
        lson[a]=Merge(lson[a],lson[b],l,m);
        rson[a]=Merge(rson[a],rson[b],m+1,r);
        t[a]=t[lson[a]]+t[rson[a]];
        return a;
    }
    
    void dfs(int x)
    {
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            dfs(v);
            T[x]=Merge(T[x],T[v],1,nn);
        }
        ans[x]=qsum(node[x],nn,1,nn,T[x]);
        upnode(node[x],1,nn,T[x]);
    }
    int main()
    {
        scanf("%d",&n);
        rep(i,1,n)
        scanf("%d",&node[i]),b[i]=node[i],T[i]=i,ncnt++;
        sort(b+1,b+1+n);
        nn=unique(b+1,b+1+n)-b-1;
        rep(i,1,n)node[i]=lower_bound(b+1,b+1+nn,node[i])-b;
    
        rep(i,2,n)
        {
            int x;scanf("%d",&x);add(x,i);
        }
        dfs(1);
    
        rep(i,1,n)
        printf("%d
    ",ans[i]);
        return 0;
    }
    View Code

    其实也可以树状数组秒解  

    递归子树的时候先减去树状数组原有的信息即可

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    /////////////////////////////////////
    const int N=1e5+100;
    
    int t[N<<5],b[N],lson[N<<5],rson[N<<5],T[N],pos,head[N],ncnt,n,ans[N],node[N],nn;
    struct Edge{int to,nex;}edge[N<<1];
    void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;}
    void upnode(int x,int l,int r,int &pos)
    {
        if(!pos)pos=++ncnt;
        if(l==r){t[pos]++;return ;}
        int m=(l+r)>>1;
        if(x<=m)upnode(x,l,m,lson[pos]);
        else upnode(x,m+1,r,rson[pos]);
        t[pos]=t[lson[pos]]+t[rson[pos]];
    }
    int qsum(int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)return t[pos];
        int m=(l+r)>>1;int ans=0;
        if(L<=m)ans+=qsum(L,R,l,m,lson[pos]);
        if(R>m)ans+=qsum(L,R,m+1,r,rson[pos]);
        return ans;
    }
    int Merge(int a,int b,int l,int r)
    {
        if(!a)return b;
        if(!b)return a;
        if(l==r)
        {
            t[a]+=t[b];
            return a;
        }
        int m=(l+r)>>1;
        lson[a]=Merge(lson[a],lson[b],l,m);
        rson[a]=Merge(rson[a],rson[b],m+1,r);
        t[a]=t[lson[a]]+t[rson[a]];
        return a;
    }
    void dfs(int x)
    {
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            dfs(v);
            T[x]=Merge(T[x],T[v],1,nn);
        }
        ans[x]=qsum(node[x],nn,1,nn,T[x]);
        upnode(node[x],1,nn,T[x]);
    }
    int main()
    {
        scanf("%d",&n);
        rep(i,1,n)
        scanf("%d",&node[i]),b[i]=node[i],T[i]=i,ncnt++;
        sort(b+1,b+1+n);
        nn=unique(b+1,b+1+n)-b-1;
        rep(i,1,n)node[i]=lower_bound(b+1,b+1+nn,node[i])-b;
    
        rep(i,2,n)
        {
            int x;scanf("%d",&x);add(x,i);
        }
        dfs(1);
    
        rep(i,1,n)
        printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    纽约顶级富婆鄙视链:4星|《我是个妈妈,我需要铂金包:一个耶鲁人类学博士的上东区育儿战争》
    2星|陈春花《顺德40年》:各种官宣的汇编,内容太虚,新信息太少
    人们喜欢传播符合自己三观的新闻,不在乎真假:4星|《环球科学》2018年12月号
    营销相关21本书
    5星|《辩论:美国制宪会议记录》:200年前的会议纪要
    3星|《品牌物理学》:理论没有实际应用案例,有推销软件的嫌疑
    关于思考的思考12本书,5星2本,4星7本
    Chrome插件 postman的使用方法详解!最全面的教程
    postman发送json请求,使用案例
    SUSE Enterprise Server 12 SP3 64 设置防火墙开放8080端口
  • 原文地址:https://www.cnblogs.com/bxd123/p/11411753.html
Copyright © 2011-2022 走看看