Loading

【题解】UOJ Round #22

// created on 22.09.17

A. 月球列车

不妨先考虑拆位,目标是判断 \(a_{i}+x\) 什么时候第 \(i\) 位为 \(1\)

即考虑 \(a_{i}\) 什么时候"越块",这个值是固定的,改变的 \(a_i\) 也是单调的。拆位对用数据结构维护 \(a_i\),每次二分一下。时间复杂度 \(O(n\log n\log a_i)\),可以拿 60pts 。

离线的部分可以利用单调性,省略二分做到 \(O(n\log a_i)\),拿 90pts 。

这是否提示了我们去省略二分?我们考虑一下每一层"越块"序列有无相似性。具体地,第 \(b\) 位的"越块"序列是 \(x_{b,i}\),注意到在 \(b\leftarrow b+1\) 时有些 \(x_{b,i}\) 会增加 \(2^{b}\),剩下的则不变。其实,对于第 \(b\) 位为 \(0\) 的,总会增加 \(2^b\),而剩下的则总不会增加。增加 \(2^b\) 的意义在于让他们总比原来的其他元素大。

我们的目的是对于每个 \(b\) 求出排名。因为 \(x\) 本身的变化也是 \(2^{b}\),考虑记 \(b\) 的序列中的元素,加与不加 \(2^b\)\(b+1\) 的序列中的排名。这个可以归并实现,查询的话直接调用数组,省去了二分过程。

B. 月球铁轨

首先有个 \(O(n^2\log a_i)\),就是暴力加线性基。然后 A 性质,线性基肯定很快就满了,剩下的元素肯定都是最大值,需要讨论的元素个数很少。B 性质二分在 Trie 上算就行了。C 性质考虑到线性基随着端点单调移动,改变的次数是 \(\log a_i\) 的。也就是说只有 \(\log a_i\) 个不同的线性基,答案分成 \(\log a_i\) 段。每次加入新元素只要更新所有线性基,观察张成空间是否变大,合并即可。

到这里大概有 55pts 了。我们不妨来猜测一下正解的复杂度。如果外层二分的话,内层应该是一个线性基的 \(\log a_i\),也就是 \(O(n\log^2 a_i)\)

我不太会做了,因为本身 \(a_i\) 的异或和左右端点拆不开。但是 Sol 给出了一个拆开的方式,仔细想想确实也有道理,这里权当一个 Trick 记录一下:对于线性基 \(T\),我们令 \(f(x,T)=\max\limits_{z\in T}x\oplus z,g(x,T)=\min\limits_{z\in T}x\oplus z\),那么有 \(f(x\oplus y,T)=f(x,T)\oplus g(y,T)\)

简单证明一下:先对 \(T\) 消元使得其变为正交线性基。此时 \(T\) 中的元素互不相交,那么 \(f(x,T)\) 相当于将 \(x\) 的位置划分为若干集合,每个集合用 \(T\) 的对应集合调整。对于 \(f(x\oplus y,T)\) 来说,调整策略应该是观察该集合 \(x\oplus y\) 是否相等,如果相等那么调整一下使得答案变大,否则肯定不调整。那么如果我们考虑将 \(x\) 的最高位尽可能地调整为 \(1\),而 \(y\) 的最高位尽可能地调整为 \(0\),就得到了我们的目的。

按照之前的观察,可能的 \(f(x,T)\) 的个数是 \(O(n\log a_i)\) 的,\(g(y,T)\) 也同样如此。那么同样扫描线,用可持久化 Trie 维护所有的 \(f(x,T)\) 。然后用所有的端点,在 Trie 上面走,判断每一位该怎么取就行了。时空复杂度 \(O(n\log^2 a_i)\)

考虑到我们其实不需要将 Trie 真正建出来,只需要求出每层的信息。具体地,考虑到最开始的询问形如对于一个 \(T\),存在若干询问 \(g(y,T):f(x,T)\) 。这样以 \(T\) 为标识符建立的组。每层新建两个新组 \(T_0,T_1\),将 \(g(y,T)\)\(f(x,T)\) 都按照选择后的下一位分组,和 \(g\) 分到一组的表示还在其 Trie 子树内,否则不在。注意到组数不会超过总数,也就是 \(O(n\log a_i)\)

提交记录:提交记录 #583916 - Universal Online Judge (uoj.ac)

C. 月球车站

首先考虑 \(a=0\) ,就是一直不翻转,那么 skip 也可以一直不翻转。然后 \(b=0\) 是一直翻转,如果原串是前缀 \(0\) 后缀 \(1\) 的拼合串,答案肯定有限。否则,如果原串是前缀 \(1\) 后缀 \(0\) 的拼合串,那么如果 \(1\) 只有一个就无力回天,否则答案无限。剩下的情况答案肯定无限。

完全不会做了,因为转移方程带 \(\max\) 。考虑到不同局面数是 \(2^n\),我们枚举每个局面,skip 做的决策,代价是 \(2^{2^{n-1}}\) 。然后转移就不需要考虑 \(\max\) 了,高斯消元,可以得到 25pts 。

接下来是一个神仙转化!现在我们考虑的是怎么简化问题,而其中最麻烦的就是 \(\max\) 转移,以及杂乱无章的转移顺序。我们能否给出一个较好的转移顺序,使得问题处理变得更简单?

我们现在考虑原问题的博弈版。从终止状态开始,我们考虑 BFS 求出所有状态,在双方都绝顶聪明的情况下,到达终止状态需要的步数。对于当前状态 \(S\),令 \(T_0,T_1\) 分别表示 \(S\) 是从一个开头为 \(0/1\) 的状态转移而来。对于 \(T_0\) 来说,伏特希望步数尽可能小,如果没有访问过 \(T_0\),那么当前就是最优方案。对于 \(T_1\) 来说,skip 希望步数尽可能大,因为 \(T_1\) 会被恰好访问两次(两种出边),所以肯定是在第二次访问时更新。

因为 \(T_0,T_1\) 是同时被访问的,且恰好被访问两次,第一次选择 \(T_0\),第二次选择 \(T_1\) 。因此每次 BFS 只会扩充恰好一个状态,所有局面的操作次数呈一条链,且步数包含了 \([0,2^{n})\) 中所有整数!

我们考虑证明所有状态都会被访问到:对于一个状态,伏特将不停操作,直到 skip 进行操作(不难发现 skip 一定要进行操作,不然必败,不符合 skip 绝顶聪明的设定),伏特就死活不操作了。这样过了 \(n\) 个字符后,整个串从左到右从低到高编码,一定比原来的串小 —— 这意味着总会走到全 \(0\),而此时伏特全部操作一遍就结束游戏了。

于是这个时候我们得到了一个关于 \([0,2^n)\) 所有状态的顺序!我们考虑此时按照链上的转移会怎么样:对于一个局面 \(i\),skip 可以操作得到 \(i-1\),也可以得到 \(x<i-1\)(两个访问局面 \(i\) 的局面,\(x\) 是第一次访问);伏特可以操作得到 \(i-1\),也可以得到 \(y>i\)\(y\) 是第二次访问)。

这个问题从复杂的图上问题到了序列上,同时 \(i\)\(i-1\) 的转移的形式也很简单。我们完完全全地简化了问题。

不过转移还是存在 \(\max\),只不过这是好处理的:显然局面按照转移顺序呈单调性:如果 \(x<y\) 但是 \(f_x>f_y\),那么 skip 可以不断地 \(i\rightarrow i-1\),而伏特只会往更大的 \(i'\) 走,所以必然经过 \(x\),此时再按照 \(x\) 的最优策略走,skip 一定能得到更大的答案。

也就是说,在 skip 转移时,选择的一定是 \(i-1\)!于是我们省去了 \(\max\) 相关的转移。此时,设 \(g_i\) 表示 \(i\rightarrow i-1\) 需要消耗的期望步数。转移是简单的。

提交记录:Submission #583943 - Universal Online Judge (uoj.ac)

总结一下,对一些图上成环的复杂转移问题,可以尝试考虑设计转移顺序,使得转移扁平化,从而得到简化问题的目标。

posted @ 2022-09-17 15:05  Qiuly  阅读(147)  评论(0编辑  收藏  举报