思路:贪心。为了保证根节点具有最大的生命值,我们可以用一个贪心策略:大剪刀能用次,那么就在前m层使用大剪刀,后更深的层使用小剪刀即可。并且题目说了,每次修剪为左右孩子到根,这个顺序天然和后序遍历一致。因此,我们就可以递归算一遍后序遍历,以及对应节点的深度;之后,再用贪心策略求出最终的答案并输出即可
注意:递归这里python有可能超时,推荐用模拟栈来写。模拟栈的后序遍历有两种写法:1.先序遍历改一下孩子的访问顺序,最后整体翻转;2.额外用state状态变量进行标记
代码:
import sys
input = lambda: sys.stdin.readline().strip()
import math
inf = 10 ** 18
def I():
return input()
def II():
return int(input())
def MII():
return map(int, input().split())
def LI():
return input().split()
def LII():
return list(map(int, input().split()))
def LFI():
return list(map(float, input().split()))
fmax = lambda x, y: x if x > y else y
fmin = lambda x, y: x if x < y else y
isqrt = lambda x: int(math.sqrt(x))
'''
'''
def solve():
n = II()
ls = [0] * (n + 1)
rs = [0] * (n + 1)
cnt = 0
for u in range(1, n + 1):
l, r = MII()
ls[u], rs[u] = l, r
if l != 0:
cnt += 1
a = [0] + LII()
m = (cnt + 1) // 2
depth = [0] * (n + 1) # 存放节点深度
order = [] # 存放后序遍历
stack = [(1, 0, 1)] # (节点, 状态, 深度)
while stack:
u, state, d = stack.pop()
if state == 0:
depth[u] = d
stack.append((u, 1, d))
if ls[u] != 0:
stack.append((rs[u], 0, d + 1)) # 由于栈是后进先出,所以先入右
stack.append((ls[u], 0, d + 1)) # 后入左,后续处理时左先弹出
else:
order.append(u)
# 题目的操作天然就是左右根,符合后序遍历
for u in order:
if ls[u] == 0:
continue
l, r = ls[u], rs[u]
if depth[u] <= m: # 贪心,上m层用大剪刀
a[u] = fmax(a[l], a[r])
else: # 下面更深的层用小剪刀
a[u] = fmin(a[l], a[r])
print(a[1])
t = 1
# t = II()
for _ in range(t):
solve()

京公网安备 11010502036488号