Codeforces1153——D. Serval and Rooted Tree(思维好题+dfs+贪心)

简介: Codeforces1153——D. Serval and Rooted Tree(思维好题+dfs+贪心)

原题链接

D. Serval and Rooted Tree

time limit per test2 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

Now Serval is a junior high school student in Japari Middle School, and he is still thrilled on math as before.


As a talented boy in mathematics, he likes to play with numbers. This time, he wants to play with numbers on a rooted tree.


A tree is a connected graph without cycles. A rooted tree has a special vertex called the root. A parent of a node v is the last different from v vertex on the path from the root to the vertex v. Children of vertex v are all nodes for which v is the parent. A vertex is a leaf if it has no children.


The rooted tree Serval owns has n nodes, node 1 is the root. Serval will write some numbers into all nodes of the tree. However, there are some restrictions. Each of the nodes except leaves has an operation max or min written in it, indicating that the number in this node should be equal to the maximum or minimum of all the numbers in its sons, respectively.


Assume that there are k leaves in the tree. Serval wants to put integers 1,2,…,k to the k leaves (each number should be used exactly once). He loves large numbers, so he wants to maximize the number in the root. As his best friend, can you help him?


Input

The first line contains an integer n (2≤n≤3⋅105), the size of the tree.


The second line contains n integers, the i-th of them represents the operation in the node i. 0 represents min and 1 represents max. If the node is a leaf, there is still a number of 0 or 1, but you can ignore it.


The third line contains n−1 integers f2,f3,…,fn (1≤fi≤i−1), where fi represents the parent of the node i.


Output

Output one integer — the maximum possible number in the root of the tree.


Examples

inputCopy

6

1 0 1 1 0 1

1 2 2 2 2

outputCopy

1

inputCopy

5

1 0 1 0 1

1 1 1 1

outputCopy

4

inputCopy

8

1 0 0 1 0 1 1 0

1 1 2 2 3 3 3

outputCopy

4

inputCopy

9

1 1 0 0 1 0 1 0 1

1 1 2 2 3 3 4 4

outputCopy

5

Note

Pictures below explain the examples. The numbers written in the middle of the nodes are their indices, and the numbers written on the top are the numbers written in the nodes.


In the first example, no matter how you arrange the numbers, the answer is 1.


In the second example, no matter how you arrange the numbers, the answer is 4.


In the third example, one of the best solution to achieve 4 is to arrange 4 and 5 to nodes 4 and 5.


In the fourth example, the best solution is to arrange 5 to node 5.

题意:

20200401134307494.png

思路:

是一个有idea但是没有写出来的题。

首先,贪心的考虑,假设对于非叶子节点x xx:

1.当该节点的操作为m a x maxmax时:该点的值为叶子节点的最大值。

2.当该节点的操作为m i n minmin时:该点要尽可能的取到最大值。

这时候要尽可能的把大的放到叶子节点数量少的点。

20200401134307494.png

比如这个图,假设1 , 2 , 3 , 4 1,2,3,41,2,3,4节点的值都是m i n minmin,那么考虑如何分配是最优的:

就是把大的尽可能分给12 , 13 12,1312,13。

实现起来就很思维了。

数组d [ i ] d[i]d[i]维护的是以i ii为根节点的子树中叶子节点的数值排名d [ i ] d[i]d[i]大的数值。

比如该节点x xx下有6个叶子节点,d [ x ] = 2 d[x]=2d[x]=2,表示这个节点最大可以是6-2+1=5,也就是第二大的数。

下面就是分类讨论了:

1.当前节点x xx为叶子节点,d [ x ] = 1 d[x]=1d[x]=1

2.当前节点x xx的值为m i n minmin,d [ x ] = ∑ y = s o n x d y d[x]=\sum_{y=son_{x}}^{}{d_{y}}d[x]=∑

y=sonxdy3.当前节点的值为m a x maxmax,d [ x ] = m i n ( d [ y ] ) d[x]=min(d[y])d[x]=min(d[y])

对于分类讨论的内容可以画图理解。

答案为叶子节点个数+1-d [ 1 ] d[1]d[1]

代码:

///#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PLL;
typedef pair<int, int>PII;
typedef pair<double, double>PDD;
#define I_int ll
inline ll read(){ll x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a, ll b, ll p){ll res = 1;while(b){if(b & 1)res = res * a % p;a = a * a % p;b >>= 1;}return res;}
const int inf = 0x3f3f3f3f;
#define PI acos(-1)
const double eps = 1e-8;
const int maxn = 3e5 + 7,mod=1000000007;
int d[maxn],a[maxn];
vector<int>g[maxn];
int n,cnt=0;
void dfs(int u){
  if(!g[u].size()){
    d[u]=1;
    cnt++;
    return ;
  }
  if(a[u]) d[u]=n;
  else d[u]=0;
  for(int t:g[u]){
    dfs(t);
    if(a[u]) d[u]=min(d[u],d[t]);
    else d[u]+=d[t];
  }
}
int main(){
  n=read;
  rep(i,1,n) a[i]=read;
  rep(i,2,n){
    int x=read;
    g[x].push_back(i);
  }
  dfs(1);
  cout<<cnt+1-d[1]<<endl;
  return 0;
}

参考


目录
相关文章
codeforces 272C. Dima and Staircase(线段树)
题目很长,看加猜加谷歌翻译才看懂了题目。每级台阶的宽都是1,但高不同,并且告诉你了,然后给你m个箱子,长和宽都告诉你,把箱子靠左放,求箱子的底部有多高。
32 0
|
7月前
八皇后问题与其深度优先搜索 (DFS) 解法
八皇后问题与其深度优先搜索 (DFS) 解法
84 1
|
机器学习/深度学习 存储 分布式计算
算法思想--分治算法
分治算法是一种常见的算法思想,其基本思想是将一个大问题分解成若干个小问题,然后通过递归的方式解决每个小问题,最后将所有小问题的解合并起来得到大问题的解。分治算法通常包含三个步骤:分解、解决和合并....
123 0
算法思想--分治算法
|
算法
【算法思维训练-剑指Offer联名 二】递归与循环篇
【算法思维训练-剑指Offer联名 二】递归与循环篇
93 0
|
存储 算法
算法刷题第八天:广度优先搜索 / 深度优先搜索--2
空间复杂度:O(min(m,n)),其中 m 和 n 分别是两个二叉树的节点个数。空间复杂度取决于递归调用的层数,递归调用的层数不会超过较小的二叉树的最大高度,最坏情况下,二叉树的高度等于节点数。
154 0
算法刷题第八天:广度优先搜索 / 深度优先搜索--2
|
机器学习/深度学习 算法
算法刷题第十天:递归 / 回溯--1
时间复杂度:O(n+m),其中 n 和 m 分别为两个链表的长度。因为每次循环迭代中,l1 和 l2 只有一个元素会被放进合并链表中, 因此 while 循环的次数不会超过两个链表的长度之和。所有其他操作的时间复杂度都是常数级别的,因此总的时间复杂度为 O(n+m)。
96 0
算法刷题第十天:递归 / 回溯--1
|
机器学习/深度学习 C++
DFS经典问题——八皇后
DFS经典问题——八皇后
265 0
DFS经典问题——八皇后
Codeforces 796D. Police Stations (思维+bfs)
Codeforces 796D. Police Stations (思维+bfs)
109 0
|
算法 前端开发 程序员
「LeetCode」剑指Offer-26树的子结构⚡️
「LeetCode」剑指Offer-26树的子结构⚡️
119 0
「LeetCode」剑指Offer-26树的子结构⚡️