像潮落潮涌,送我奔向自由。|

寂静的海底

园龄:3年2个月粉丝:59关注:15

【题解】LOJ#6041 | 后缀数组 数据结构 莫队

本文用 sa 表示后缀排序数组,rk 表示后缀排名数组,hti=lcp(sai1,sai)


研究了一会出来了,据说有 LCT 维护 SAM 的做法,但这肯定不适合我们普及组选手,我们直接开莽。

首先把给出的序列倒过来方便描述,现在要求区间内两个后缀 LCP 最大,看到 LCP 直接上后缀数组,转化成最大化 height 上的区间最小值 minp(rk(i)+1,rk(j)]htp

现在考虑区间询问的信息肯定是按照 rk 排个序后选相邻两个,因为如果不选相邻两个的话只会让区间更大,最值更小,所以接下来要维护一个区间排好序后相邻二者信息的最值,这种东西常见做法有找支配对和暴力分块。

因为求的是二者之间的最小值,这玩意不是很好找支配对,考虑直接暴力做掉:因为“区间排好序后相邻两者之间的信息”是“难以合并但方便加入”的信息,考虑直接上莫队。

每次加入一个数会在数组里找到它的前驱后继并把它和它前驱后继的关系给删除掉,然后加入它前驱和后继的关系,维护一个根号平衡的数据结构维护 O(1)O(n) 的最值,然后复杂度瓶颈就在莫队移动这里查找前驱后继会产生一个 log

所以考虑直接将带加入的前驱后继转成带删除的前驱后继,带删除的前驱后继可以先桶排然后拿链表维护前驱后继及删除操作即可。这个时候我们的莫队也要随之改变成回滚莫队,在这里不是常见的不删除莫队,而是不加入莫队,如果不会写这玩意可以我下面的代码。

时间复杂度是低劣的 O(nlogn+nq),操作常数虽然很大内存也不连续,但是跑不满,我的实现甚至可以跑进 1s

我的实现(基本没压行,很好写,码量约5k)


保守了,根号还是保守了。

Caiest_OIer 教的超级聪明做法!

将 Height 从大到小加入则每个询问的时间为其中两个点第一次连通的时间,拿 bitset 存下所有询问,直接在合并的时候求两个bitset的交去更新答案!!!时间复杂度是炫酷的 O(n(n+q)ω)

太牛了!


菜鸡玩不来 SAM + LCT,还能再给力点吗?

考虑继续上面那个做法,现在变成了如下问题:

一个图,每次链接两个点,查询编号在区间 [l,r] 中存在任意两个点联通的最早时间,这个是集合关系看上去不是很好做只能拍 bitset,但是任意两个点都不联通看上去是一个很强的条件,并且具有可二分性,所以有了如下思考:

考虑洪水填充地给连通块染色,然后如果求出每个时间点的状态的话可以直接二分一个时间,然后查询区间内是否恰好有 rl+1 种颜色,这个玩意用不着上区间数颜色,考虑对每个编号维护编号 < 它的最大相同颜色编号 prei,查询区间 premax 是否大于 l,如果有的话说明区间内不符合条件,这个东西就查前驱后继区间 max,容易做到 O(logn) 修改 O(logn) 查。

因为要考虑带加边给连通块染色这种东西,考虑使用启发式合并均摊成 O(nlogn) 次单点修改颜色,然后现在变成了在修改颜色的这个修改序列上二分,所以考虑直接整体二分做,递归右边撤回操作再递归左边,时间复杂度是高贵的小常数 O((n+q)log3n/loglogn),实现精细可以空间 1log,感觉还是打不过 O(n+qlog2n) 的 SAM + LCT 啊呜呜。

posted @   寂静的海底  阅读(18)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起