题目:
线段树合并裸题。那种返回 int 的与传引用的 merge 都能过。不知别的题是不是这样。
#include#include #include #include using namespace std;const int N=1e5+5,M=N*17*5;int n,m,a[N],tp[N],rt[N],hd[N],xnt,to[N],nxt[N],ans[N];int tot,ls[M],rs[M],siz[M];int rdn(){ int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return fx?ret:-ret;}void add(int x,int y){ to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}void merge(int &x,int y){ if(!x){x=y;return;} siz[x]+=siz[y]; if(ls[y])merge(ls[x],ls[y]); if(rs[y])merge(rs[x],rs[y]);}/*int merge(int x,int y){ if(!x||!y)return x+y; int d=++tot; siz[d]=siz[x]+siz[y]; ls[d]=merge(ls[x],ls[y]); rs[d]=merge(rs[x],rs[y]); return d;}*/int query(int l,int r,int cr,int L,int R){ if(!cr)return 0;if(l>=L&&r<=R)return siz[cr]; int mid=l+r>>1,ret=0; if(mid>=L)ret=query(l,mid,ls[cr],L,R); if(mid >1; if(mid>=p) insert(l,mid,ls[cr],p); else insert(mid+1,r,rs[cr],p);}void dfs(int cr){ for(int i=hd[cr],v;i;i=nxt[i]) dfs(v=to[i]),/*rt[cr]=*/merge(rt[cr],rt[v]); ans[cr]=query(1,m,rt[cr],a[cr],m); insert(1,m,rt[cr],a[cr]);}int main(){ n=rdn(); for(int i=1;i<=n;i++)a[i]=tp[i]=rdn(); sort(tp+1,tp+n+1); m=unique(tp+1,tp+n+1)-tp-1; for(int i=1;i<=n;i++)a[i]=lower_bound(tp+1,tp+n+1,a[i])-tp; for(int i=2,d;i<=n;i++) { d=rdn(); add(d,i); } dfs(1); for(int i=1;i<=n;i++)printf("%d\n",ans[i]); return 0;}