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
  • 相关阅读:
    02.简单的DOM操作
    03.获取和设置元素特性的值
    异常为"当IDENTITY_INSERT设置为OFF时" 的解决
    GridView的RowCommand事件中取得行索引 技巧
    01.判断页面加载完成的方法
    今天新开了博客园
    C#巧用anchor和dock设计复杂界面(控件随着窗体大小的变化而变化)
    C#如何使用webbrowser控件制作一个简易的IE浏览器(菜鸟级)
    断箭——不相信自己的意志,永远也做不成将军
    成长与成功
  • 原文地址:https://www.cnblogs.com/bxd123/p/11411753.html
Copyright © 2011-2022 走看看