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\n",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\n",ans[i]);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/bxd123/p/11411753.html
今日推荐