1. 程式人生 > 其它 >2022春每日一題:Day 38

2022春每日一題:Day 38

題目[USACO17JAN]Promotion Counting P

從根節點dfs一遍,樹狀陣列維護進入和出去時這個節點的貢獻,一減就是答案

程式碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#define lowbit(x) x&-x
const int N=1e5+5; 
using namespace std;
struct pos
{
	int v,id;
	pos(int vv,int ii)
	{
		v=vv;id=ii;
	}
	pos(){
	}
	friend bool operator < (pos a,pos b)
	{
		return a.v<b.v; 
	}
}nums[N];
int n,a[N],fs[N],fe[N],tot;
vector <int> g[N];
namespace fenwick
{
	struct fw
	{
		int c;
	}e[N];
	void modify(int x,int v)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		    e[i].c+=v;
	}
	int query(int x)
	{
		int ret=0;
		for(int i=x;i;i-=lowbit(i))
		    ret+=e[i].c;
		return ret;
	}
}
using namespace fenwick;
void dfs(int u,int fa)
{
	++tot;
	modify(a[u],1);
	fs[u]=tot-query(a[u]);
	for(int i=0;i<g[u].size();i++)
	{
		int k=g[u][i];
		if(k==fa)
		    continue;
		dfs(k,u);
	}
	fe[u]=tot-query(a[u]);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int v;
		scanf("%d",&v);
		nums[i]=pos(v,i);
	}
	for(int i=2;i<=n;i++)
	{
		int v;
		scanf("%d",&v);
		g[v].push_back(i);
		g[i].push_back(v);
	}
	sort(nums+1,nums+1+n);
	int last=-1,now=1;
	for(int i=1;i<=n;i++)
	{
		if(last!=nums[i].v)
		    last=nums[i].v,now=i;
		a[nums[i].id]=now;
	}
	dfs(1,0);
	for(int i=1;i<=n;i++)
	    printf("%d\n",fe[i]-fs[i]);
	return 0;
}