LOJ #6878. 生不逢时

发布时间 2023-11-06 18:45:58作者: 275307894a

题面传送门

原题不卡常,但是被某个出题人搬到校内 OJ 上开了 2s 1024MB,怎么回事呢?

首先我们可以把回文改写成 \(x\operatorname{xor} x^R=0\),这样只需要维护 \(x\) 的下 \(\frac{m}{2}\) 位即可。

考虑一个常见的套路,将 \([l,r]\) 拆成 \(O(\log V)\) 个区间,这些区间满足前若干位是定的,后若干位可以任选。

则可以设出一个 dp 状态:设 \(dp_{i,j,S}\) 表示考虑前 \(i\) 个数,后 \(j\) 位是任选的,前 \(S\) 位是定的,转移平凡。这样直接转移看上去复杂度是 \(O(\log^n V)\) 的,大概可以过 \(n\leq 4\)

但是实际上,我们可以说明,\((j,S)\) 二元组的取值只有 \(O(m2^n)\) 个。考虑我们给一个已有的状态集合转移一个 \([L,R]\),对于一个最终状态,其 \(j\) 会取最大值,分类讨论:

  • 若其最大值在 \([L,R]\) 取到,则其 \(j\) 位之前只有 \(2\) 种情况。
  • 若其最大值在原状态取到,则其异或的 \([L,R]\) 只有 \(2\) 种情况。

综上,每次转移只会增加 \(O(1)\) 个状态,可以进一步证明其只有 \(2^n\) 种,不想写了(

所以暴力建立 01Trie 转移能过 \(n\leq 18\) 或者 \(m\leq 30\),能过很多分!

然后发现 \(2^{\frac{n}{2}}\) 是可以接受的,于是直接 meet in middle 就行了!

吗?

发现好像是不太行的,因为转移是 \(O(m)\) 的,状态是 \(O(m\times 2^{\frac{n}{2}})\) 的,寄了。

考虑优化转移,转移的瓶颈在于取 \(\max\),转移式子中有 \(\max\) 前缀和一下,转移完再差分回去就行。

这样转移只需要转移 Trie 同一层的节点,复杂度是 \(O(m2^{\frac{n}{2}})\) 的。

这样就能过原题数据了,但是不太能过校内 OJ。

一点技巧:

  • 不需要记录前缀和之后差分出来的值,因为没啥用。
  • 垃圾回收可以少 \(\frac{1}{2}\) 内存。
  • unsigned int instead of long long

大概能过,目前应该是 LOJ 最优解 submission