线段树合并

洛谷P3605 [USACO17JAN] Promotion Counting P

#include<bits/stdc++.h>
using namespace std;
int cnt,a[100010],b[100010],fa[100010],rt[100010],ans[100010],tot;
struct jade
{
	int lc,rc,num;
}t[4000010];
int n;
vector<int> q[100010];
void pushup(int pos)
{
	t[pos].num=t[t[pos].lc].num+t[t[pos].rc].num;
}
int insert(int pos,int l,int r,int v)
{
	if(!pos)
	{
		tot++;
		pos=tot;
	}
	if(l==r)
	{
		t[pos].num++;
		return pos;
	}
	int mid=(l+r)>>1;
	if(v<=mid)
	{
		t[pos].lc=insert(t[pos].lc,l,mid,v);
	}
	else
	{
		t[pos].rc=insert(t[pos].rc,mid+1,r,v); 
	}
	pushup(pos);
	return pos;
}
int merge(int x,int y,int l,int r)
{
	if(!x)
	{
		return y;
	}
	if(!y)
	{
		return x;
	}
	if(l==r)
	{
		t[x].num+=t[y].num;
	}
	int mid=(l+r)>>1;
	t[x].lc=merge(t[x].lc,t[y].lc,l,mid);
    t[x].rc=merge(t[x].rc,t[y].rc,mid+1,r);
    pushup(x);
    return x;
}
int ask(int pos,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	{
		return t[pos].num;
	}
	int mid=(l+r)>>1;
	int res=0;
	if(x<=mid)
	{
		res+=ask(t[pos].lc,l,mid,x,y);
	}
	if(y>mid)
	{
		res+=ask(t[pos].rc,mid+1,r,x,y);
	}
	return res;
}
void dfs(int x)
{
	for(int i=0;i<q[x].size();i++)
	{
		int to=q[x][i];
		if(to==fa[x])
		{
			continue;
		}
		dfs(to);
		rt[x]=merge(rt[x],rt[to],1,cnt);
	} 
	ans[x]=ask(rt[x],1,cnt,a[x]+1,cnt);
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i]; 
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	cnt=unique(b+1,b+1+n)-b-1;
    for(int i=1;i<=n;i++)
    {
    	a[i]=lower_bound(b+1,b+1+n,a[i])-b;
    	rt[i]=insert(rt[i],1,cnt,a[i]);
	}
	for(int i=2;i<=n;i++)
	{
		int x;
		cin>>x;
		fa[i]=x;
		q[x].push_back(i);
		q[i].push_back(x);
	}
	dfs(1);
	for(int i=1;i<=n;i++)
	{
	    cout<<ans[i]<<endl;
	}
	return 0;
}
posted @ 2025-07-15 22:03  BIxuan—玉寻  阅读(11)  评论(0)    收藏  举报