题目传送门: 戳这里
每个叶节点任意赋值,根据节点的特性求根节点的最大值
对于任意一个节点,如果使他的子节点都尽量大,那么该节点的值就是最大的。
每个节点记当前的最大值,是1-k中的第几大值,记为SZ,根据max和min的特性推算。
如果当前节点上的操作是max,那么就从其子节点上选取SZ最小的,这里其实也可以发现,SZ的值在某种意义上来说,代表着与这个点相连的叶节点的个数,但是我说不清楚T_T。
如果当前节点上的操作是min,要想知道当前节点上的最小值,就要知道于该节点相连的叶节点的个数,如果总共有k个叶节点,当前节点下连接着n个,那么最大值就是k-n+1,也就是第n大的值,因为SZ表示叶节点的个数,所以当前节点是min的时候,我们需要把子节点的SZ相加,就是当前节点的最大值。
#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
const int maxn=3e5+5;
int leave;
int M[maxn],SZ[maxn];
vector<int> adj[maxn];
int dfs(int v);
int main(){
ios::sync_with_stdio(false);
int len;
cin>>len;
rep(i,1,len+1)
cin>>M[i];
rep(i,2,len+1){
int root;
cin>>root;
adj[root].Push(i);
}
leave=0;
int k=dfs(1);
cout<<leave-k+1<<endl;
re 0;
}
int dfs(int v){
if(getLen(adj,v)==0){
leave++;
re SZ[v]=1;
}
int num;
if(M[v]){ //max
num=INT_MAX;
rep(i,0,getLen(adj,v)){
int u=adj[v][i];
num=min(num,dfs(u));
}
}else{ //min
num=0;
rep(i,0,getLen(adj,v)){
int u=adj[v][i];
num+=dfs(u);
}
}
re SZ[v]=num;
}