codeforces1153D. Serval and Rooted Tree 贪心

题目传送门: 戳这里


每个叶节点任意赋值,根据节点的特性求根节点的最大值
对于任意一个节点,如果使他的子节点都尽量大,那么该节点的值就是最大的。
每个节点记当前的最大值,是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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值