baka's trick

众所周知,双指针适用于一类固定左端点,右端点具有单调性的问题,由于每个点只会被删一次,所以令加入/删除的时间复杂度为 O(B),总时间复杂度 O(nB)

而对于一些信息,加入是简单的,但是删除是困难的(例如 gcd、min)等,这时我们考虑 baka's trick 把删除扔掉。

考虑设一个阈值 p,假设当前双指针两个端点是 l,r,要维护的信息是 f(l,r),我们开两个栈,一个栈维护 limid,f(i,mid),另一个栈维护 mid<ir,f(mid+1,r),当 l 或者 r 右移时,我们只需要弹栈就行。要得到 f(l,r) 时,只需要合并两个栈顶的信息即可。当 l 移出 mid 时,令新的 mid 为原来的 r,则我们把另一个栈维护的信息从 mid<ir,f(mid+1,i) 重构成 mid<ir,f(i,r),然后令 l 为原来的 midmid 为原来的 r,然后这个栈就变成维护 limid,f(i,mid) 的了,以此类推下去。

这样我们只会加入和合并,令加入/合并的时间复杂度为 O(C),总时间复杂度 O(nC)

一个例子:求 lr 的数量使得 gcdi=lrai1。我们要维护的信息是 f(l,r)=gcd(al,,ar),加入和合并复杂度均为 O(logV),时间复杂度 O(nlogV)

一个不太行的例子:求 lr 的数量使得 [l,r] 内的物品做背包(令背包容量为 m)的最大价值小于等于 k。我们要维护的信息是 f(l,r)=knapsack(l,,r),即对区间内物品做背包后的结果。虽然加入的时间复杂度为 O(m),但是合并时间复杂度为 O(m2),所以总时间复杂度是 O(nm2),在某些题上可能需要更快的解法。

作者:dcytrl

出处:https://www.cnblogs.com/dcytrl/p/18544036

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   dcytrl  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示