模拟 Enterprise Recognition Program


这题是离线,相对好模拟
题意:
一个公司的管理为树状结构
有两种发放钱的方式。

  • 单个人的奖金
  • 对单个人以及所有上级发放奖金
    有两个询问的方式
  • 询问单个人的奖金
  • 询问下属的奖金加上自己的奖金
    思路:
    用一个二维数组earn[N][3]来储存 第一种方式获得的、第二种方式得到的(用于向上继承)、下属的奖金
    用树结构储存完后,dfs搜索一遍节点,更新earn[][1]和earn[][2].
    (https://img2022.cnblogs.com/blog/2781289/202203/2781289-20220322083927614-1386639216.png)
#include
using namespace std;
const int N = 1e6+7;
using ll = long long;
ll earn[N][3];
#define IOS ios::sync_with_stdio(false),cin.tie(0);
struct edge{
	int next;	//储存相同节点的边的序号便于遍历 
	int to; 
}edge[N];
int num_edge;
int head[N];
void pre()
{
	memset(head,-1,sizeof head);
}
void add_edge(int from,int to)
{
	edge[num_edge].next=head[from];  //第一次执行时候 为 -1 ,呼应 dfs的条件
	edge[num_edge].to=to;
	head[from]=num_edge++;      //这里的是以每个节点的第一个子节点为尾巴,其他的子节点逐一添在尾巴后面.


}
void dfs(int u)    //从右往左遍历每个节点的子节点
{
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v = edge[i].to;
		dfs(v);
		earn[u][1]+=earn[v][1];//奖金方式分配的,继承子节点的奖金 
		earn[u][2]+=earn[v][0]+earn[v][1]+earn[v][2];//储存 unit的总奖金  自己赚的+分配的+unit的; 
	}
}
signed main()
{
	IOS;
	pre();
	int n,m,q;
	int boss;
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++)
	{
		int num;
		cin>>num;
		add_edge(num,i);
		if(num==0)
		{
			boss=i;
		}
	 } 
	 int t,v,e;
	 for(int i=1;i<=m;i++)
	 {
	 	cin>>t>>v>>e;
	 	if(t==1)
	 	{
	 		earn[v][0]+=e;
		}else
		{
			earn[v][1]+=e;
		}
	 }
	 dfs(boss);
	 for(int i=1;i<=q;i++)
	 {
	 	cin>>t>>e;
	 	if(t==1)
	 	{
	 		cout<