题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)

Posted dysyn1314

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)相关的知识,希望对你有一定的参考价值。

loj3265 「USACO 2020.2 Platinum」Delegation

因为是最大化最小值,考虑二分答案。

设当前二分的答案为(K)。则要判断是否有一种划分方式,使得每条链的长度都至少为(K)

不妨以(1)为根,对整棵树dfs。记(fa(u))(u)的父亲节点。dfs(u)函数求出一个值(f(u)),或判断在当前的(K)下无解。有解时,我们把(u)的子树划分为若干条长度(geq K)的链,并选择一条未完结的链(允许这条链长度(<K))覆盖(u)(fa(u))之间这条边。这条链会被交给dfs(fa(u))继续处理。而(f(u)),就是这条返回给(fa(u))的链的最长长度。dfs(u)函数要做的,就是在保证其他每条链长度都(geq K)的前提下,让(f(u))的长度尽可能大。

考虑dfs(u)函数的实现。先递归(u)的所有儿子,每个儿子(v)会带来一条长度为(f(v)+1)的链(这个(+1)就是(u,v)之间的边,它没有被算在(f(v))中)。把得到的这些链按长度排序。此时我们有两种选择:

  • 方案一:把所有这些链两两匹配。(如果链的数量是奇数,就加一条长度为(0)的链)。要求每对匹配链的长度和(geq K)。并令(f(u)=0)
  • 方案二:挑出一条链作为(f(u)),让其余的链两两匹配。如果能匹配成功,则令(f(u)=)这条挑出来的链的长度。

这里的“两两匹配”,我们可以做一个简单的贪心:让最大的链和最小的链匹配,第(2)大的链和第(2)小的链匹配......。如果存在某一对链的长度和(<K),说明匹配失败,无法找到合法的匹配方案。

(u=1)时,我们显然只能选择方案一,即把所有链都匹配起来。否则无解。

(u eq 1)时,本着让(f(u))尽可能大的原则,我们优先考虑方案二。如果无法实现方案二,再考虑方案一是否可行。若也不可行,则无解。

现在的问题是,如果选择方案二,我们该如何在保证其它链能够成功匹配的前提下,挑出一条尽可能长的链作为(f(u))呢?考虑两条长度分别为(x,y)的链,若(x<y),则若挑出(y)这条链后其它链能够成功匹配,挑出(x)后其他链也一定能成功匹配(这相当于把匹配中的(x)换成(y),有一条链变得更长了,匹配结果不会变差)。故可以二分把那条链作为(f(u)),判断是否可行即可。

时间复杂度(O(nlog^2n))

参考代码

loj3266 「USACO 2020.2 Platinum」Equilateral Triangles

图片来源:洛谷用户:ix35

观察一个曼哈顿等边三角形:

技术图片

红线、蓝线分别是(BC,AC)的曼哈顿距离。

把线段平移,得到下图:

技术图片

此时,(BC)的曼哈顿距离是(color{red}{ ext{红}})(+)(color{green}{ ext{绿}})(AC)(color{blue}{ ext{蓝}})(+)(color{green}{ ext{绿}}),于是我们可以得到:(color{red}{ ext{红}})(+)(color{green}{ ext{绿}})(=)(color{blue}{ ext{蓝}})(+)(color{green}{ ext{绿}}),所以(color{red}{ ext{红}})(=)(color{blue}{ ext{蓝}})。同理可知:(AO=BO=CO)(曼哈顿距离)。也就是说,(O)(Delta ABC)在曼哈顿距离意义上的“外心”。

考虑枚举这个外心(O),再枚举(O)(A,B)的距离(r)。大力讨论(A,B)所在的象限(四种情况)。此时(A,B)的位置就已经确定了。考虑(C)。首先(C)一定在和(A,B)相反的象限,且(OC=r)。可以发现这样的(C)一定在一条斜(45^{circ})角的线上(即平行于矩形某条对角线的线)。对每条这样的斜线做前缀和即可(O(1))查询出(C)的数量。

时间复杂度(O(n^3))

参考代码

loj3267 「USACO 2020.2 Platinum」Help Yourself

把所有线段按左端点排序。设(dp_0[i][r])表示考虑了前(i)条线段,最大右端点在(r)时,有多少满足条件的线段子集;(dp_1[i][r])表示此时所有满足条件的线段子集,每个线段子集的的连通块数之和;(dp_2[i][r])表示此时所有满足条件的线段子集,每个线段子集的的连通块数的平方,之和......。

一般地,定义(dp_k[i][r])表示考虑了前(i)条线段,最大右端点在(r)时,所有满足条件的线段子集,每个线段子集的并的连通块数的(k)次方之和((0leq kleq K))。设对于一个线段集合(s)(operatorname{maxendpos}(s))表示(s)中所有线段的最大右端点,(cnt(s))表示(s)的连通块数。则:
[ dp_k[i][r]=sum_{sin[1,i], operatorname{maxendpos}(s)=r}cnt(s)^k ]
考虑新加入一个线段(i)。从(dp[i-1][j])转移到(dp[i][?])。分三种情况讨论:

  • (j<l_i),此时加入线段(i)会使右端点变为(r_i),且连通块数(+1)
  • (l_ileq jleq r_i),此时加入线段(i)会使右端点变为(r_i),且连通块数不变。
  • (j>r_i),此时加入线段(i)既不改变右端点也不改变连通块数。

发现问题主要在于连通块数(+1)时的转移不好处理。考虑现在有一(dp_k[i][j]),把它的连通块数(+1),看它的值会如何变化:
[ trans(dp_k[i][j])=sum_{s}(cnt(s)+1)^k=sum_ssum_{t=0}^{k}{kchoose t}cnt(s)^t=sum_{t=0}^{k}{kchoose t}dp_t[i][j] ]
由此,此时再考虑(dp_k[i][?])的转移式。初始时,令每个(dp_k[i][j]=dp_k[i-1][j]),表示在线段集合中不选线段(i)的情况。然后考虑选线段(i)的情况:
[ dp_k[i][r_i]+=sum_{j=0}^{l_i-1}trans(dp_k[i-1][j])+sum_{j=l_i}^{r_i}dp_k[i-1][j]dp_k[i][x]+=dp_k[i-1][x]quad(x>r_i) ]
其中(trans(dp_k[i-1][j]))可以(O(K))求。故时间复杂度为(O(n^2K^2))

考虑优化。

首先,(sum_jtrans(dp_k[i-1][j]))就等于(trans(sum_jdp_k[i-1][j]))。因为我们在推(trans)时并没有用到(j)具体的值,只是用(i,j)来表示了一堆“线段的集合”。把这些集合先并起来(作为一个更大的集合),再转移也是一样的。

根据套路,不难想到用线段树去维护所有的(j)。线段树上,设一个节点所代表的区间为([l,r])。我们在这个节点上存(K+1)个值,分别为:((sum_{j=l}^rdp_0[i][j]),(sum_{j=l}^rdp_1[i][j]),dots,(sum_{j=l}^rdp_K[i][j]))

则从(i-1)(i)的转移相当于:

  • (r_i)这个位置执行线段树单点加操作,让它的值(+trans(sum_{j=0}^{l_i-1}dp_k[i-1][j]))。其中求((sum_jdp_k[i-1][j]))要用到线段树区间求和
  • (r_i)这个位置执行线段树单点加操作,让它的值(+(sum_{j=l_i}^{r_i}dp_k[i-1][j]))
  • 对线段树(r_i+1sim 2n)这些位置执行区间乘操作,全部( imes2)

注意,区间所有的查询操作要在修改操作之前进行。这样查到的才是(dp_k[i-1])的值。

时间复杂度(O(nK^2+nlog nK))

参考代码

以上是关于题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)的主要内容,如果未能解决你的问题,请参考以下文章

loj6274 数字 题解

LOJ6276:果树——题解

LOJ6346:线段树:关于时间 ——题解

LOJ132. 树状数组 3 :区间修改,区间查询 题解

题解——loj6280 数列分块入门4 (分块)

loj2765 - 冒泡排序 题解