UOJ Logo jiry_2的博客

博客

UOJ Round #13 题解

2016-04-10 20:19:58 By jiry_2

大家好这里是写题面的JRY。

最近因为种种原因,UR 跳票了半个多月的时间,不过终于,新的一场 UOJ Round 还是和大家见面啦。(在某学堂的提醒下,管理员们终于想起来还有UR这回事了...

因为写题面的人比较懒,所以这一次的标题就用了杜老师的格式:)

希望大家能够喜欢这一次的题目owo

Yist

By matthew99

算法一

直接状压每一种可能的子序列,时间复杂度O(2npoly(n)+q),期望得分30分。

算法二

二分之后贪心每次删除最小的数,判断是否可行。由于删除一个数会让更大的数“更容易”被删,所以这个算法显然是正确的。

时间复杂度O(n2logn),期望得分60分。

算法三

使用平衡树等数据结构优化算法二,时间复杂度O(qnlog2n),由于常数大可能较难通过90分的数据。

算法四

我们考虑到对于一个数,删除它最小需要的区间长度是多少,如果我们在序列左右都加上一个无穷小且没有被删除,考虑找到它左边没有被删除的第一个比它小的位置u,右边没有被删除的第一个比它小的位置v,那么需要的区间长度就是(u,v)这个开区间的长度减去这个区间中所有比它小且需要删除的数的个数。答案就是所有数对于的区间长度的最小值。

从左往右扫一遍,并用set或者什么其他数据结构维护一下,可以求出所有的uv,然后从小到大加入,用树状数组或者什么其他数据结构维护一下即可求出区间中所有比它小且需要删除的数的个数。时间复杂度O(qnlogn),期望得分90分。

算法五

算法四中提到,需要的区间长度就是(u,v)这个开区间的长度减去这个区间中所有比它小且需要删除的数的个数,实际上,我们只需要用开区间的长度减去这个区间中所有需要删除的数的个数即可。

考虑一个数,假设区间中有一个数需要删除且比它大,那么显然这个比它大的数所对应的区间长度比原数短,所以这样显然不会影响答案(因为我们要求的只是最小值)。

所以我们只要求出uv即可。

这样很多劣于线性的算法都能AC,这里列举几个:

维护A的单调栈,并在上面二分,由于常数小可以AC。

用ST表加上二分,然后加上一些优化O(1)去除一些显然不能更新答案的位置,也可以AC。

从大到小加数,所有被删除的和已经被加入的未被删除的位置记为1,其他位置记为0,则显然uv分别就是左边和右边的第一个0,用并查集很好维护,如果不计读入的话时间复杂度为O(qnlogn)或者O(qnα(n))

算法六:

为了避免成为辣鸡卡常出题人,接下来我来讲讲线性做法,我的程序可以在时限的大约三分之一内出解。

其实很简单,对于所有被删除的位置,从大到小,每次暴力找uv,并把所有访问过的地方标记,如果暴力的时候遇到了标记过的地方,那么可以发现原来访问到这个地方的数显然对应的区间更短,所以这个时候可以不用继续找uv,直接考虑下一个位置即可,这样每个位置只会访问一次,若不考虑读入,则时间复杂度O(qn),期望得分100分。

题外话:

我看到开场就有几个人交了正解的第一步:只找最大的一个数暴力找uv更新答案,首先我样例是随机的所以你们很容易通过,其次我第一个点也是随机的所以你们也能过第一个点的十分,其他点应该都是过不了的,我想说的是你们就不会认真分析一下问题再提交么,实际上如果你们只找最大的几个更新答案也是很难有很多分的。考虑一下有两个阶梯,一个阶梯就是左右两边都是很小的未被删除的数,中间是比两边大的被删除的数和比被中间所有所有被删除的数都要大的未删除的数,那么如果第一个阶梯的数比第二个阶梯的数大而且第一个区间更短,那么更新答案的应该是第二个阶梯中的最大值,这样前面很多很多个数对应的区间都不是答案。

Ernd

By PoPoQQQ

因为A题和C题难度偏高所以出了道简单题平衡一下难度

ctb上瘾的出题人

算法一

对于subtask1,n20

暴力枚举接哪些水果,线性统计得分,时间复杂度 O(n×2n)

用DFS的方式可以将复杂度降低至 O(2n)

期望得分 10 分。

并没有什么卵用的算法。

算法二

对于subtask2,n1000

我们定义“段”为满足对于其中任意相邻元素 ii+1 ,满足接到第 i 个水果后可以接到第 i+1 个水果的极长子区间。

考虑暴力dp,定义 fi 为以第 i 个水果结尾的接水果序列的最大总得分,那么有:

fi=max(fi,fj+1| 接到第 j 个水果后可以接到第 i 个水果)

fi=max(fi,fj1+(ij+1)2| 第 i 个水果和第 j 个水果属于同一段)

枚举 j 进行转移,时间复杂度 O(n2),期望得分 20 分。

算法三

我们考虑如何优化第一部分转移。

我们将水果都放在二维平面上,第 i 个水果变成一个坐标为 (ai,bi) 的点,那么容易发现,接到一个果子后,能接到的其他果子都在这个点的 [45,135] 范围的方向上。

旋转坐标系,将每个点变为 (biai,bi+ai),那么接到一个果子后,能接到的其他果子都在这个点的右上方。

问题变成了一个二维偏序问题,用树状数组维护上升子序列即可。

观察subtask4,n5×105,答案不超过104,这意味着任意一段的长度都不会超过 104=100

第一部分转移使用算法三,第二部分转移暴力,时间复杂度 O(nlogn+100×n) ,期望得分 40 分。

算法四

现在开始考虑如何优化第二部分转移。

注意到一段内的元素在按照 biai 排序后可能不连续,但相对顺序不会改变,因此我们不用担心转移顺序的问题。

这部分转移每段之间彼此独立,因此我们考虑对于每段内部分别计算。

观察转移方程 fi=max{fj1+(ij+1)2},设 P=fj1+(ij+1)2 ,那么有:

(fj+j22j)=2i×j+(Pi22i)

我们发现这个式子可以斜率优化,将每个决策点 j 化为平面上的点 (j,fj+j22j) ,维护一个上凸包即可。

注意到我们维护的是上凸包而查询斜率 2ii 单调递增,因此我们需要用一个栈而不是队列来维护这个凸包。

当然你要二分斜率也是完全可以的。

时间复杂度 O(nlogn),期望可以通过全部测试点拿到 100 分。

算法五

考虑用另一种方法优化第二部分转移。

观察到对于决策点 j<k,随着 i 的增大,(ij+1)2 的增长速率永远大于 (ik+1)2 的增长速率,这意味着一旦某一时刻 fj1+(ij+1)2>fk1+(ik+1)2,那么决策点 k 将会永远不可能成为最优决策点,决策点 k 可以删除。

由此我们发现了决策单调性,利用单调栈+二分的方法维护有效决策点,时间复杂度 O(nlogn),期望可以通过全部测试点拿到 100 分。

什么你问我subtask3是干嘛的?

照顾常数写残党/数据结构爆搞党/乱搞党。

以上。

Sanrd

By Stilwell

算法一

容易发现我们需要求的是lr这段数的次大质因子之和,其中次大质因子定义为可重集的次大。

一个最简单的方法是将每个数都质因子分解,对于前50\%的数据,rl107,这一段数的质因子总个数是O((rl)logr)的。

预处理出r范围内的质数,考虑使用埃氏筛法进行分解,设当前质数为p,那么范围内第一个被p整除的数为lpp,筛法消耗的时间和质因子总个数是相同的。

时间复杂度O(r+(rl)logr),期望得分50分。

算法二

原问题等价于求1n的次大质因子之和。

考虑用[1,n]范围内的所有数做一个乘积背包,设f[i]表示现在乘积为i的数的最大质因子之和,升序枚举质因子可以保证当前质因子是转移后的最大质因子,转移前的最大质因子就是需要求的次大质因子,背包生成的每个数都是不重复的,所以可以直接计入答案。

容易发现f[i]的可能取值只有两种,0或i的最大质因子,取决于当前枚举的质数能不能组成i。这样表示状态明显非常浪费,可以尝试优化。

对于一个数x(xn)x的次大质因子一定n,所以>n的质数我们可以考虑批量转移。

对于一个状态i,在背包时还能转移的质数需要ni,不妨直接用ni来表示状态。

g[j]表示ni=j的数的最大质因子之和,由于ni的取值只有O(n)种,所以状态数缩减为O(n),原先iip的转移变化为jjp

那么现在问题就转化为这样两部分:

  1. ni>n的质数个数。
  2. n的质数完成g[j]的背包。

先来解决第一部分,设p1pmn的质数,且pi<pi+1

P[i][j][1,j] 范围内与前i个质数互质的数的个数,需要求的即为 P[m][j]

l=jpi,容易得到以下递推式 P[i][j]=P[i1][j]P[i1][l]

递推时只需要计算niO(n)个状态就能完成转移。

设质数密度为O(1logn),那么暴力递推的计算量可以估计为 i=1nO(ilogi)+i=1nO(nlogn)O(nlogn)

pi+1>j时,一定满足P[i][j]=1

所以,当pi2>jpiP[i][j]=P[i1][j]1

因此,不必重新计算pi2>j的情况,记录j最近一次被更新时的i的值,设为prej,在调用P[i][j]时,将编号prej+1i间的质数计入。

考虑对于每个ni计算有多少质数需要转移,计算量可估计为 i=1nO(ilogi)+i=1nO(nilogni)

后半部分一定大于前半部分,故复杂度可以估计为 i=1nO(nilogni)O(0nnxdxlogn)=O(n34logn)

完成了质数部分的计算,考虑g[j]部分的计算,暴力转移需要枚举每个质数再枚举每个状态,复杂度同样为O(nlogn)

回想前一部分是如何优化的,考虑如何省去p2>j=ni时的运算。

p2>jjp<pn,所以这些状态在以后的转移中只能再加入一个n的质数了,可以这样优化:

  1. 这一部分转移不再进行。
  2. 记录最后一次更新g[j]时的p,最后再计算相应的贡献。
  3. 当转移到这些g[j]时,不更新g[j],直接统计剩下还能使用的质数个数,计算相应的贡献。

优化后复杂度和第一部分一样为O(n34logn)

时间复杂度O(n34logn),期望得分100分。

评论

啊..好大
啊..好大
前排!
T1有n^2的60分算法……还好写…… http://uoj.ac/submission/59991
评论回复
matthew99:你把后面那些正解做法都用暴力实现。。。我们就得到了很多很多好写的60分算法咯
前排%%%%
啊..好大
『这样很多劣于线性的算法都能AC』为啥根本A不了555
评论回复
matthew99:这是不是有点像一个人在抱怨:这道题有很多算法能AC,可是我为啥没A?2333
WuHongxun:回复 @matthew99:我写了个并查集的做法然后被卡T了。。
matthew99:回复 @WuHongxun:你常数太丑了吧。。。一般的并查集0.5s不到诶
WuHongxun:回复 @matthew99:5555
前排
论评测机杀。。
啊.. 人类智慧是不会败的!
为什么B题要卡O(Nlog^2N),分治写起来也是很辛苦的。。。 QAQ(AQ)*
评论回复
wzj:http://uoj.ac/submission/60608
辣鸡卡常出题人!把我线性做法卡读入了!交了好几发90分,最后才发现卡读入!辣鸡卡常出题人!@matthew99
评论回复
matthew99:惨啊
我觉得T2subtask3很有用啊,dp时由于第i个接到之后必定可以接到第i+4个,接完第i+4个一定可以接到第i+8个以后的,所以就不用考虑接完第i个就直接接第i+8个以后的了。
评论回复
bzh:另外,对于第二部分,假设从第i个最长可以连到第j个,则dp时只要考虑连到j-1,j-2,j-3,j-4,j-5就行了
T3 算法一复杂度不是 O(r+(rl)loglogr)

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。