题解 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\neq 1\)时,本着让\(f(u)\)尽可能大的原则,我们优先考虑方案二。如果无法实现方案二,再考虑方案一是否可行。若也不可行,则无解。

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

时间复杂度\(O(n\log^2n)\)。

参考代码

loj3266 「USACO 2020.2 Platinum」Equilateral Triangles

图片来源:洛谷用户:ix35

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

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

把线段平移,得到下图:

此时,\(BC\)的曼哈顿距离是\(\color{red}{\text{红}}\)\(+\)\(\color{green}{\text{绿}}\),\(AC\)是\(\color{blue}{\text{蓝}}\)\(+\)\(\color{green}{\text{绿}}\),于是我们可以得到:\(\color{red}{\text{红}}\)\(+\)\(\color{green}{\text{绿}}\)\(=\)\(\color{blue}{\text{蓝}}\)\(+\)\(\color{green}{\text{绿}}\),所以\(\color{red}{\text{红}}\)\(=\)\(\color{blue}{\text{蓝}}\)。同理可知:\(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\)次方之和(\(0\leq k\leq K\))。设对于一个线段集合\(s\),\(\operatorname{maxendpos}(s)\)表示\(s\)中所有线段的最大右端点,\(cnt(s)\)表示\(s\)的的连通块数。则:
\[
dp_k[i][r]=\sum_{s\in[1,i],\ \operatorname{maxendpos}(s)=r}cnt(s)^k
\]
考虑新加入一个线段\(i\)。从\(dp[i-1][j]\)转移到\(dp[i][?]\)。分三种情况讨论:

  • \(j<l_i\),此时加入线段\(i\)会使右端点变为\(r_i\),且连通块数\(+1\)。
  • \(l_i\leq j\leq 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_s\sum_{t=0}^{k}{k\choose t}cnt(s)^t=\sum_{t=0}^{k}{k\choose 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+1\sim 2n\)这些位置执行区间乘操作,全部\(\times2\)。

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

时间复杂度\(O(nK^2+n\log nK)\)。

参考代码

原文地址:https://www.cnblogs.com/dysyn1314/p/12403868.html

时间: 2024-07-31 04:27:40

题解 loj3265 3266 3267 USACO 2020.2 Platinum(全)的相关文章

金三银四,磨砺锋芒;剑指大厂,扬帆起航(2020年最全大厂WEB前端面试题精选)下

金三银四,磨砺锋芒:剑指大厂,扬帆起航(2020年最全大厂WEB前端面试题精选)下 引言 元旦匆匆而过,2020年的春节又接踵而来,大家除了忙的提着裤子加班.年底冲冲冲外,还有着对于明年的迷茫和期待!2019年有多少苦涩心酸,2020年就有更多幸福美好,加油,奥利给!怀着一颗积极向上的心,来面对未来每一天的挑战! 所谓"兵马未动,粮草先行",我们打响明天的战役也需要精神食粮来做后勤保障才是.在此我整理了多位从业者和我在2019年底至2020年初的一厂面试精选题,希望对磨砺锋芒.奋发向上

PMP备考资料 | 2019/2020年PMP全真模拟题 、一模、二模、三模试题 | PMP章节练习题 | 附带详细答案解析 --- 项目整合管理 等(PMBOK&#174;第六版)

PMP备考资料 | 2019/2020年PMP全真模拟题 .一模.二模.三模试题 | PMP章节练习题 | 附带详细答案解析 --- 项目整合管理 等(PMBOK®第六版),获取:http://t.cn/A6POWgMw 原文地址:https://www.cnblogs.com/chunlynn/p/12252179.html

6546. 【GDOI2020模拟4.8】USACO 2020 Open Contest, Platinum(circus)

题目描述 Farmer John 马戏团的 N 头奶牛( 1 ≤ N ≤ 10^5 )正在准备她们接下来的演出.演出在一棵结点编号为 1 - N 的树上进行.演出的"起始状态"可以定义为一个整数 1 ≤ K ≤ N 以及奶牛 1 - K 在树上的结点分布,使得没有两头奶牛位于相同的结点. 在一场演出中,奶牛们可以进行任意次数的"移动".在一次移动中,一头奶牛从她的当前所在结点移动到一个未被占据的相邻结点.称两个起始状态是等价的,如果一个状态可以通过一系列移动到达另一

USACO 2017 February Platinum

第二次参加USACO 本来打算2016-2017全勤的 January的好像忘记打了 听群里有人讨论才想起来铂金组三题很有意思,都是两个排列的交叉对问题 我最后得分889/1000(真的菜)先发下当时做的,A的之后补 T1.Why Did the Cow Cross the Road题目大意:给出两个N个排列(N<=100,000),允许把其中一个排列循环移动任意位,a[i]表示i在第一个排列中的位置,b[i]表示第二个,定义交叉对(i,j)满足a[i]<a[j]且b[i]>b[j],求

USACO 2017 January Platinum

因为之前忘做了,赶紧补上. T1.Promotion Counting 题目大意:给定一个以1为根的N个节点的树(N<=100,000),每个节点有一个权值,对于每个节点求出权值比它大的子孙的个数. 思路:肯定先要求出dfs序,首先无脑想到主席树,后来发现只要按权值从大到小处理就不用那么麻烦了. #include<cstdio> #include<algorithm> using namespace std; char B[1<<26],*S=B,C;int X;

USACO 2017 FEB Platinum nocross DP

题目大意 上下有两个长度为n.位置对应的序列A.B,其中数的范围均为1~n.若abs(A[i]-B[j]) <= 4,则A[i]与B[j]间可以连一条边.现要求在边与边不相交的情况下的最大的连边数量.n <= 10^5. 在Gold里,此题的数据范围是1000,我们完全可以用简单的最长公共连续子序列的DP方法来做. 范围大了之后,可以观察到对于一个数A[i],它所能转移的状态最多只有9个,那么就可以顺序扫描A数组,设F[i][j]表示当前连得最后一条边为(A[i],B[to[i][j]])的最

【USACO 2018 JAN Platinum】救生牛

问题描述 农夫约翰为他的奶牛们开了一个游泳池.简单起见,泳池每天在时刻 1 开门,一直到时刻 10^9才关闭. 为确保奶牛的安全,他雇佣了 N只救生牛,分别编号为 1,2,-,N.每只救生牛都有固定的工作时段.救生牛 i(1≤i≤N)的工作时段可以用两个整数 si,t?i?? 描述,表示救生牛 i 的工作时段为 (si,ti] .例如,一个救生牛的 si=4,ti=7,则它在时刻 4+1=5 开始工作,在时刻 7 结束工作,共覆盖三个时刻(不含起始时刻,含结束时刻). 现在约翰难以负担救生牛的高

2020年最全Spring面试题总结,“金三银四”戴上口罩不畏惧!

附上spring核心价值导图 ?1. 什么是 spring? Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用, 但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标是简化Java企 业级应用开发,并通过POJO为基础的编程模型促进良好的编程习惯. 2. 使用 Spring框架的好处是什么 ? 轻量:Spring 是轻量的,基本的版本大约2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是 创建或查找依赖

2020年最全多线程面试题总结,助你“金三银四”过五斩六!

1.多线程有什么用? 1)挥多核CPU 的优势随着工业的进步,现在的笔记本.台式机乃至商用的应用服务器至少也都是双核的,4 核.8 核甚至 16 核的也都不少见,如果是单线程的程序,那么在双核 CPU 上就浪费了 50%, 在 4 核 CPU 上就浪费了 75%.单核 CPU 上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了.多核 CPU 上的多线程才是真正的多线程,它能让你的多段逻辑同时工