P3605 [USACO17JAN]Promotion Counting晋升者计数 线段树合并 or 树状数组

Posted bxd123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 Edgeint 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 Edgeint 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

 

以上是关于P3605 [USACO17JAN]Promotion Counting晋升者计数 线段树合并 or 树状数组的主要内容,如果未能解决你的问题,请参考以下文章

P3605 [USACO17JAN]Promotion Counting P (dsu+线段树)

P3605 [USACO17JAN]Promotion Counting P (线段树合并)

P3605 [USACO17JAN]Promotion Counting P (线段树合并)

P3605 [USACO17JAN]Promotion Counting P(树状数组)

P3605 [USACO17JAN]Promotion Counting P(树状数组)

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