UOJ Logo zhoukangyang的博客

博客

UOJ NOI Round #8 Day1 题解

2024-07-13 20:36:57 By zhoukangyang

最酷的排列

idea,sol,data,std from Kubic

别急。

下面是 Rainbow_sjy 代更。

首先我们只需要考虑相邻元素的交换。

从后往前扫,最终位置 i 的数不可能比 ii 后面的数更小。

用小根堆维护后缀中的数,碰到酷的位置,就弹出最小的计入答案。这个答案是下界,而且是可以构造得到的。

里外一致

idea from cmk666,solution from zjy0001

记区间 [l,r] 中颜色 i 出现 ci(ci>0) 次,如果 i 只出现在 S 中,那么有 1 种选择方法,如果只出现在 U/S 中,那么有 1 种选择方法,否则有 2ci2 种选择方法。

考虑构造形式幂级数 Fi(x)=(x1)2+2cix,F(x)=iFi(x) ,如果有 K 种不同的颜色在区间 [l,r] 中出现,那么答案就是 [xK]F(x)

考虑记 y=(x1)2 那么 F(x) 每一项的指数和是固定的 K,于是我们可以设 Gi(x)=1+2cix,求出 G(x)=iGi(x),那么答案就是 [xK]i(x1)2(Ki)xi[xi]G(x)=i(1)Ki(2(Ki)Ki)[xi]G(x)

接下来观察模数的性质,因为Gi(x)=1+2cix,ci>0,所以有 i64,[xi]G(x)0(mod264),于是我们只需要求出 G 的前 64 项即可。

对于 ci64,我们不用关心,因为 Gi(x)1(mod264),对 G 的求解没有影响。

否则,对于 1k63,依次统计出 dk=i[ci=k],于是 G(x)=k=163(1+2kx)dk,容易用组合数预处理出 (1+2kx)dk 的每一项系数,并且对于每一个 k,其只有前 63k 的值在模意义下不为 0,如果我们从大到小依次枚举 k 乘起来,它依然保持这个性质,于是单次计算 G(x) 的复杂度就是 Θ(log2P) 的了。

如果用扫描线配合树状数组求出 dk,那么总时间复杂度就是 Θ((n+q)lognlogP+qlog2P) 的。

二维抄袭检测

idea,data,std from unputdownable, solution from unputdownable,zhoukangyang

n2

一个点只有两个出边。

如果两者字符不一样,那么直接走对应字符的出边就行。

难处理的是两条出边字符相等的情况。

但是 n2,注意到向右走一定不劣,所以贪心先匹配第一行,然后再往第二行匹配即可。

总复杂度 O(L+nm+qlogm),也可以做到单组查询 O(1)

n3

贪心失效了!真的失效了吗?

考虑我们的贪心什么时候会挂。 S=xxxxxxxxxxxxxxxxxxxxxT= xxxxxxxxxxxxaaaaaaaaaxaaaaaaaaaaaaaaaaxxxxxxxxxxxaa 考虑选择一个位置提前往下拐。

注意到如果在蓝色分支之前就往下拐,一定不比蓝色优,否则蓝色一定能接到那个路径上去。

所以应该选择最后一个能往下拐的位置往下拐,然后就是 n=2 的部分了。

注意到能往下拐的位置一定满足 T2,x=T1,x+1,或者在末尾,而这个是好维护的

记得在两种贪心中取较大的一个。

总复杂度仍是 O(L+nm+qlogm),也可以做到单组查询 O(1)

n4

贪心还有救吗? S=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxT= xxxxxxxxxxxxxxxxxxaaaaaaaxaaxaxaxaxaxaxaxaaaaaaaaxaaaaaaaaaaaaaaaaaaaaaaaxxxxxxxxxxxxxxxxxxxxxxx

这样子可以把上述贪心卡死。

但是如果能找到一个直达第三排的位置,从那个位置往下拐贪一下,就还有救。

因为考虑所有从第二行转移到第三行的列,如果这一列的第一行无法到达,那么可以被走完第一行再接 n=3 的贪心;

而当我们找到一个能直达第三行的位置,和 n=3 的情况就差不多了,可以证明这是最优的决策之一。

观察到能到第三排的位置应该满足 T2,x=T1,x+1T3,x=T1,x+2;或者 x 在第一行贪心匹配部分(上图红色)末尾两个字符(需要特判)。

将走完第一行再接 n=3;第一行走到剩下一个再接 n=3;选择最后一个能往下拐的位置往下拐;找到最后一个能直达第三行的位置往下拐四种贪心拼起来即可通过 n=4

总复杂度仍是 O(L+nm+qlogm),也可以做到单组查询 O(1)

L,m,q1000

对于询问暴力跑一个朴素的 DP,记 fi,j 表示能否走到 (i,j) 这个点,单次询问复杂度 O(nm)

总复杂度 O(L+nm+qnm)

L,m,q104

注意到 DP 状态只有 01,直接压位用位运算做 DP,单组询问复杂度 O(m)

总复杂度 O(L+nm+qm)

n7

贪心彻底没救了,因为此时路径的形态会变得相当复杂。

注意到 n 很小,考虑想办法维护上述动态 DP。

首先将矩阵转换为斜矩阵以方便理解(第 i 行向右平移 i1 个字符),这样每一步是向右或者向右下走,即第 i 步一定走到第 i 列。

维护 DP,第 i 列的状态只和第 i1 列的状态以及需要匹配的字符有关。

难点在于转移矩阵会随着询问的字符串而改变。

想办法固定每个位置的转移矩阵。

注意到如果先贪心在第一行匹配,那么在和第一行匹配上的这个区间内,转移矩阵是固定的。

直接动态 DP 维护此时的 DP 状态;如果下面的行已经没有可达的位置了,那么贪心匹配第一行一定是最优的;否则跳到下方第一个可以到达的行,然后递归。

预处理动态 DP 矩阵,查询时只需要做至多 n 遍向量乘区间的转移矩阵。

视实现的不同复杂度大约 O(LlogL+n3mlogm+qn3)

n10

注意到矩阵很小,可以压位,单次矩乘 O(n2)

上猫树,注意到每次乘的是单个转移矩阵,而不是若干转移矩阵的积,其中非 0 元素只有 O(n) 个。

这样预处理时单次矩乘 O(n)

复杂度 O(LlogL+n2mlogm+qn2)

由于实测时间瓶颈在 SA 预处理上,所以即使你的询问多一个 n 或者多一只 log,如果卡常较为精细也能通过。

谢罪

部分乱搞获得了 84,复杂度错误的 O(m2n2) 以及 O(m2n) 也通过了。

评论

在这个范围下 m2^n 为啥会被称为是错误的啊。
评论回复
Zhu_Xiangyu:感觉是写错了,应该是q2^n
T2 似乎没有两个log卡过去的。只有根号能过
评论回复
Diu:我t2两个log过了 https://uoj.ac/submission/700664
pp_orange:回复 @Diu:我草,把所有 dp 放一起,然后离线下来跑多轮树状数组,同时在轮间差分。离线下来大幅减小内存导致的常数,差分又让常数折半。天才啊。
Kevin090228:回复 @pp_orange:没必要这么复杂,正常写树状数组就能过,https://uoj.ac/submission/698904,只需要差分一下就行
T2 O(nq0.5+qlog2alogloga) 通过了。
评论回复
Rainbow_sjy:有不少人 64*64*log(64) 过的,因为这个数据范围卡不掉。
T3 可以状压然后建 DFA 之后链剖然后 SA+树上 k 级祖先做到 O(SA(nm+L)+2nm+qn)
评论回复
Kevin090228:为什么 LHF 是神?
T3 部分乱搞获得了 100
评论回复
yaoxi_std:不对,我的做法好像是有理有据的,只是漏掉了几步转移
怎么 d1t1 还是别急
怎么 d1t1 还是别急
怎么 d1t1 还是别急
You AK IOI!!!

发表评论

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