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;
其实也可以树状数组秒解
递归子树的时候先减去树状数组原有的信息即可
#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;
以上是关于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(树状数组)