模拟 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<