提高组经典题选做

本文解析了两道NOIP竞赛题目:“保卫王国”与“疫情控制”。针对“保卫王国”,介绍了如何利用动态规划求解最小代价的问题;对于“疫情控制”,提出了一种二分答案加贪心匹配的方法。

[NOIP2018 D2T3]保卫王国

Description

给定一棵树,每个点都有一个点权 a i a_i ai

q q q次询问,每次小 Z Z Z会给出一组询问 x , a , y , b x,a,y,b x,a,y,b,表示第 x x x个节点不能选/必须选,第 y y y个节点不能选/必须选时,这棵树的最小代价。

定义一棵树的最小代价为: 在树上选定的节点满足任何一条边的两个端点至少一个节点被选中时,所有选中的节点的点权之和的最小值。

n , q ≤ 1 0 5 n, q≤10^5 n,q105,时限 2 s 2s 2s

Solution

状态设计 d p i dp_i dpi表示,以 i i i为根的子树的最小代价;其中, d p i , 0 dp_{i,0} dpi,0表示节点 i i i不能选,否则必须选。

状态转移:

d p i , 0 = ∑ d p s o n , 1 dp_{i,0}=\sum dp_{son,1} dpi,0=dpson,1
d p i , 1 = ∑ m i n ( d p s o n , 0 , d p s o n , 1 ) + a i dp_{i,1}=\sum min(dp_{son,0},dp_{son,1})+a_i dpi,1=min(dpson,0,dpson,1)+ai

然后,我们再拆分下重儿子与轻儿子的贡献,写下式子:

d p i , 0 = g i , 0 + d p w s , 1 dp_{i,0}=g_{i,0}+dp_{ws,1} dpi,0=gi,0+dpws,1
d p i , 1 = g i , 1 + m i n ( d p w s , 0 , d p w s , 1 ) dp_{i,1}=g_{i,1}+min(dp_{ws,0},dp_{ws,1}) dpi,1=gi,1+min(dpws,0,dpws,1)

这里 g i , 0 g_{i,0} gi,0表示所有轻儿子 s s s d p s , 1 dp_{s,1} dps,1之和, g i , 1 g_{i,1} gi,1表示所有轻儿子 s s s m a x ( d p s , 0 , d p s , 1 ) max(dp_{s,0},dp_{s,1}) max(dps,0,dps,1)之和并加上 a i a_i ai的值。

然后这题就成为了一道动态 d p dp dp的板子题。

时间复杂度 O ( 2 3 × q l o g 2 n ) O(2^3×q log^2n) O(23×qlog2n)

[NOIP2012 D2T3]疫情控制

Description

H 国有 n n n个城市,这 n n n个城市用 n − 1 n-1 n1条双向道路相互连通构成一棵树, 1 1 1号城市是首都,也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位: 小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

Solution

一道有传奇意义的题目。

首先,我们先总结一下题面: 我们要让这些军队所移动的时间的最大值最小。此时,我们看到了“最大值最小”的字眼,果断二分答案

假设目前二分的值是 m i d mid mid,显然,任何军队移动的时间都不能超过 m i d mid mid。同时,任何军队在其花费的时间不超过 m i d mid mid的前提下,显然越往上越好,因为在往上走的过程中管束到的叶节点的数量单调不减;还有一些节点可能会跨过根节点去其他的子树,但是跨到的一定是另外一个子树的根,也就是 1 1 1号节点的另一个儿子,不然不符合“军队越往上越好”的定理。

我们将这些军队分成两类。第一类是在规定时间内不能跨过根到达其他子树的军队,第二类就是能在规定时间内跨过根到达其他子树的军队。对于第一类,它们要尽量往上走,走到不能走再停;对于第二类,它们同样要尽量往上走,而且也要考虑这些节点是否要跨过根去其他子树

此时一种简单的想法是,对于所有第二类军队,先将它们移动到根,然后贪心匹配。更具体地说,我们先处理第一类军队,第二类军队暂时删去。在此时的树上跑一遍 d p dp dp(或者是递推)求出在以各个 1 1 1号节点儿子为根的子树内是否有叶子节点不受管辖。如果有一个节点,满足它是根节点的一个儿子并且在以其为根的子树内存在节点不受管辖,那么就将这个节点的父边权值扔进数组 B B B中。然后,我们找到所有第二类军队,将它们跳到根,并用数组 A A A记录下这些节点的剩余时间。此时我们的目标是,在 A A A中选择一些数与 B B B中的所有数匹配,要求任何一个 B B B中的数被匹配的次数有且仅有一次,并且 A A A中匹配的那个数不小于 B B B中匹配的那个数。我们可以将 A , B A,B A,B排序,然后贪心扫一遍就可以了。

但是这种做法有一个大问题: 假设根节点的一个儿子是 p p p,在以 p p p为根的子树中有一个第二类军队 t t t,现在 t t t走到了且剩余时间为 3 3 3,但是 p p p的父边权值是 4 4 4,看到 3 < 4 3<4 3<4就以为回不去了,但事实上是能回去的——也就是根本不到根节点,直接驻守在 p p p即可;到了 p p p就停,根本不到根节点,这里却以为不行。

在这里插入图片描述

假设 t t t走到了 p p p,剩余时间为 r e s t rest rest p p p的父边权值为 w w w。出现问题当且仅当 2 w > r e s t 2w>rest 2w>rest

再仔细思考一下这个问题在什么情况下是灾难性的: 灾难性是指会导致WA,而非灾难性指逻辑上有问题但最终结果仍然正确。如果 p p p B B B数组中,也就是在以 p p p为根的子树中存在叶子节点不受管辖,显然需要一个军队来补充。但是,第二类军队 t t t走到了根节点之后,就误以为不能返回了,从而放弃了对 p p p中叶子结点的管辖,从而可能导致误判二分的值不可行……

考虑军队 t t t跨过了根节点驻守了另外一个子树且 p p p B B B中时,这个军队是否有必要去跨过根节点来驻守其他子树。如果军队 t t t跨过根节点去了另一个节点 f f f,那么一定需要另外一个在 p ′ p' p的军队 t ′ t' t p p p这里补充。假定 p p p的父边权值为 a a a f f f的父边权值为 b b b p ′ p' p的父边权值为 c c c。此时, t t t这支军队耗费了 a + b a+b a+b的时间, t ′ t' t这支军队耗费了 a + c a+c a+c的时间;另外一种方法是,让 t t t呆在 p p p这里,让 p ′ p' p去驻守 f f f,那么耗费的是 b + c b+c b+c

即,我们要比较 m a x ( a + b , a + c ) max(a+b,a+c) max(a+b,a+c) b + c b+c b+c的大小。由于 2 a > r e s t 2a>rest 2a>rest,而 a + b ≤ r e s t a+b≤rest a+brest,所以 b < a b<a ba,所以 a + c > b + c a+c>b+c a+c>b+c

由于总有 a + c > b + c a+c>b+c a+c>b+c,所以总有 m a x ( a + b , a + c ) > b + c max(a+b,a+c)>b+c max(a+b,a+c)>b+c,所以第一种方案比第二种方案差。此时,我们要让 t t t这一支军队呆在 p p p一定是最优的选择之一。我们还要结合感性理解,“如果这一支军队的剩余时间本身就不多了,而且它自己还没有完成自己的责任(驻守以 t t t为根的子树),就不要让它跑了”,这样避免了“自己管不好还要管别人”的情况的发生。

特判掉了这一类情况后,之前的思路就是正解了。我们通过匹配的成功或失败可以调整二分上下边界。


总结一下每次 c h e c k check check我们干些什么。

①所有第一类节点尽量往上跳;
②跑一遍 d p dp dp,得到 B B B数组;
③所有第二类节点尽量往上跳,不能跳到根节点
④求出当前每个节点的剩余时间 r e s t rest rest
⑤特判一些““自己管不好还要管别人”的第二类军队,让这些军队按兵不动;
⑥其他所有节点跳到根节点,并求出数组 A A A
⑦将 A , B A,B A,B分别排序;
⑧匹配;
⑨通过匹配的成功与失败调整二分上下边界。

我们发现仍然有一些小问题,这里阐述一下:
①③倍增跳,而不是暴力跳;注意预处理倍增数组;
d p i dp_i dpi代表以 i i i为根的子树中是否存在叶子节点没有被管辖,转移显然;

考虑二分的次数是 O ( log ⁡ w ) O(\log w) O(logw),每次二分的复杂度为 O ( ( m + n ) log ⁡ n ) O((m+n)\log n) O((m+n)logn),于是总时间复杂度为 O ( log ⁡ w ( n + m ) log ⁡ n ) O(\log w (n+m) \log n) O(logw(n+m)logn)

可以通过本题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值