Atcoder AGC001 解题报告
\(A.\ BBQ\ Easy\)
简要题意:
将\(2N\)个数字分成两个一组,每一组的价值是较小的数字,求总的价值最大的分组方案。
题目解法:
题目相当于将数字分成两组\(A\)和\(B\),使得分别排序后,都是\(A_i \leq B_i\),并且最大化\(\sum A_i\)。
将原数组排序,设为\(\{S_i\}\),那么有\(S_1 \in A\)。
我们的目标是最大化\(\sum A_i\),等价于最小化\(\sum B_i\)。
那我们就可以用\(S_1\)将\(S_2\)拼掉,也就是将\(S_2\)放在\(B\)中,这一定是最优的。
此时问题规模就缩小了,就可以继续做了。
所以说,答案就是排序之后奇数位的数字和。
\(B. \ Mysterious\ Light\)
简要题意:
有一个边长是\(N\)的正三边形,从距离一个顶点\(X(X<N)\)处,平行于一条直线射入三角形。
与特殊的光线不同,这一束光可以被自己的轨迹反射(当然,也可以被三角形反射)。
可以证明,这束光最终一定会回到出发点,求出这束光回到出发点之前经过的路径长度。
题目解法:
这道题,个人感觉就是肉眼观察题,如图:
(忘了在图中标出长度和点了。。。将就一下吧。)
通过图,我们发现,如果用第一条和第二条分割三角形,就可以得到一个平行四边形。
而且光束一定是从其中一个大小是 \(\frac{2 \pi}{3}\)的角射入,最终只有两种情况:
- 光束正好到达出发点(另一个 \(\frac{2 \pi}{3}\) 角),此时一定有:长边长度\(a\)是短边长度\(b\)的倍数。
- 否则,就可以转化成一个子问题:长边是\(y\),短边是\(x \mod y\)。
那么我们就可以用类似欧几里德算法的递归方式求解了。
\(C. \ Shorten\ Diameter\)
简要题意:
给定一个无根树,可以进行若干次如下操作,使得这棵树直径长度不超过\(K\)。
选择一个叶子,将其及其邻边删除。
求最少进行多少次操作,能够达成目标。
题目解法:
最开始想的是重心一定不会删,于是以重心为根树形DP。。。
事实证明我\(naive\)了,一是重心可能删,二是我的\(DP\)应该是\(N^3\)或\(N^2\log{N}\)的。
好吧,最终还是参考了其他人的解法:
题目是最小化删点个树,也就是最大化留下的点的个树。
于是分\(K\)是奇数还是偶数讨论:
(1) \(K \equiv 0 (\mod 2)\)
此时,我们一定能找到一个点,剩下的点中距离这个点最远的点,距离不超过\(\frac{k}{2}\)。
(1) \(K \equiv 1 (\mod 2)\)
此时,我们一定能找到一条边,剩下的点中距离这条边最远的点,距离不超过 \(\frac{k-1}{2}\) 。
这两种情况我们都能枚举枚举点或边,再\(O(N)\)计算,总的就是\(O(N^2)\)。
\(D. \ Arrays\ and\ Palindrome\)
简要题意:
原本有两个数组\(\{ A \}\)和\(\{ B \}\),满足以下性质:
- \(\sum A = N\), \(\sum B = N\), \(Ai, Bi \in N_{+}\)
- 只有每一个位置都相同的长度为\(N\)的数组,才满足这两个性质:
(1):将这数组分段:开头\(A_1\)个数,再\(A_2\)个数,再\(A_3\)个数\(\dots\)以此类推,使得每一段都是回文的。
(2):将这数组分段:开头\(B_1\)个数,再\(B_2\)个数,再\(B_3\)个数\(\dots\)以此类推,使得每一段都是回文的。
但是现在,这两个数组都丢了,只知道\(N\)、\(M\) (\(\{ A \}\)的长度) 以及将\(\{ A \}\)打乱之后的数组\(\{ C \}\)。
请构造一组原来的\(\{A \}\)和\(\{ B \}\)。
题目解法:
我们思考一下那个回文的限制:
如果我们将每一组的回文对应位置(也就是一定相等的位置)连一条边,那么这\(N\)个点是在同一个联通块里的。
我们思考一下这些边怎么来的,如果存在一个长度为\(len\)的区间回文限制,那么我们就能连\(\left\lfloor\frac{len}{2}\right\rfloor\)条边。
众所周知,\(N\)个点要联通,最少要\(N-1\)条边。
那么就可以得到,如果\(\{ C \}\)中有大于两个奇数,就无解了,这是因为每一个奇数段,都会空出一个点,如果有三个空出来的就会少两条边,连树都不能构成了。
满足这个条件,我们就可以构造\(\{ B \}\)了,就是按照将每一段的中心错开,将每一条边错开的原则。
具体的说:将\(\{C\}\)的奇数放在两端,就是\(\{ A \}\)了,再将\(A_1-=1\),\(A_M+=1\),就是\(\{ B \}\)了,代码真简单。
\(E. \ BBQ\ Hard\)
简要题意:
给出\(N\)个二元组\((A_i,B_i)\),求下面式子的值:
题目解法:
我们回想一下\(x+y \choose x\)的组合意义:从\((0,0)\)到\((x,y)\)的路径条数。
那么我们可以拓展到\((x_1-x_0)+(y_1-y_0) \choose (x_1-x_0)\)就是从\((x_0,y_0)\)到\((x_1,y_1)\)的路径条数。
可以发现,从\((-x_0,-y_0)\)到\((x_1,y_1)\)的路径条数就是和题目一样的形式了。
那么我们可以将题目先变形:
现在就只要考虑求出任意两个数之间的贡献了,这个经过上面的转化很好做:
我们考虑一个\(x \in [-2000,2000], y \in [-2000,2000]\)的直角坐标系,
最开始,在所有的\((-A_i,-B_i)\)上加一个一,之后DP,用组合数的递推就好了。
\(F. \ Wide\ Swap\)
简要题意:
给定一个排列,每次操作可以交换差值为1并且距离大于\(K\)的两个数。
求出能构造出来的字典序最小的排列。
题目解法:
因为距离大于\(K\)这个限制很恶心,考虑在这个排列的逆(也就是位置排列)上操作:
那么每次就是选相邻的而且差值大于\(K\)的两个数交换,而且因为是逆,所以我们现在是要最大化字典序了。
能够发现,如果两个数差值小于等于\(K\),那这两个数的相对位置一定不会改变。
就相当于是前面的数向后面的数连一条边,之后的拓扑序就是一个合法的排列,也可以最大化字典序了。
但是这样有\(O(N^2)\)条边,不可行,考虑利用传递性去掉一些边,例如\((x,y)\)、\((y,z)\)和\((x,z)\),其中\((x,z)\)没用。
这样的话,我们就从后往前向后面的点连边,但是只需要连两条:这个数\(\pm K\)的范围,正负各连一条到满足要求的最近的点(因为其他的合法的点一定会连到这两个点)。
这个连边操作可以用线段树简单实现,之后就是跑一遍拓扑序的事儿了。