当前位置: 首页 > news >正文

一种“用平衡树修改自己”的算法

最近在考试时发现可以用 \(FHQ-Treap\ O(n\log^2n)\) 做一些事情,觉得很有趣,就记录下来。若有与他人重复,还请提醒。


起因是考场上遇到了这样一个问题:

有两个数列 \(a,c\),满足 \(c_i<i\)。从前往后对于每个位置,求出一个数对 \(p_i=(a_i,d_i)\),其中 \(d_i\in [c_i,i)\),要求 \(d_i\)\([c_i,i)\)\(p_i\) 最小的位置。对于两个数对排序方式是:先比较 \(a_i,a_j\) 的大小,若相同比较 \(p_{d_i}\)\(p_{d_j}\) 的大小。要求时间复杂度为 \(O(n\log^2n)\)

容易发现,假如我们在求解 \(p_i\) 的时候,已经知道了前 \(i-1\) 个位置的 \(p\) 数组排名,那么我们可以用线段树简单维护每个 \(d_i\)。难点在于如何排序。

容易发现当你塞入一个新的数对 \(p_i\) 时,比 \(p_i\) 大的数对排名会 \(+1\)。因此考虑可以进行区间加的 \(FHQ-Treap\)。但是难点在于如何利用平衡树自身的排名进行分裂。因为假如我们只按照每个位置上记录的排名进行排序,可能会出现懒标记暂未下放的情况;而分裂操作会破坏树结构,因此普通平衡树中的查排名操作也无法实施。

考虑不下放标记,而让节点通过向上一步一步爬的方式找标记。定义 getnum(x) 函数表示我们从 \(x\) 开始,一直执行向父亲跳和给 \(x\)\(num\) 加上当前点的懒标记值的操作,最终得出的数就是这个位置的真实排名,代码如下:

inline int getnum(int x){int re=num(x);x=fa(x);while(x) re+=fl(x),x=fa(x);return re;
}

由于平衡树深度为 \(O(\log n)\),所以这一操作的时间复杂度即为 \(O(\log n)\)。由于 \(split\) 操作本身就有一个 \(\log\),所以现在 \(split\) 的总时间复杂度为 \(O(\log^2n)\)。代码如下:

inline int getnum(int x){int re=num(x);x=fa(x);while(x) re+=fl(x),x=fa(x);return re;
}
inline bool operator<(suf x,suf y){return x.fs!=y.fs?x.fs<y.fs:getnum(x.ls)<getnum(y.ls);
}
inline void push_up(int x){sz(x)=sz(ls(x))+sz(rs(x))+1;
}
inline void down(int x,int k){fl(x)+=k,num(x)+=k;
}
inline void push_down(int x){down(ls(x),fl(x)),down(rs(x),fl(x)),fl(x)=0;
}
inline void split(int x,suf v,int &a,int &b,int af,int bf){if(!x){a=b=0;return;}push_down(x);if(v<val(x)) split(ls(x),v,a,ls(b=x),af,x),fa(x)=bf;else split(rs(x),v,rs(a=x),b,x,bf),fa(x)=af;push_up(x);
}
inline int merge(int x,int y){if(!x||!y) return x|y;push_down(x),push_down(y);if(rk(x)<rk(y)) return rs(x)=merge(rs(x),y),fa(rs(x))=x,push_up(x),x;return ls(y)=merge(x,ls(y)),fa(ls(y))=y,push_up(y),y;
}

这样我们就可以用总时间复杂度 \(O(n\log^2n)\) 的做法 \(AC\) 这个问题了。由于时间复杂度非均摊,所以理论上可以做可持久化。另外,本题理论上可以将区间加改为区间反转等更复杂的区间操作。

http://www.jsqmd.com/news/46185/

相关文章:

  • 2025年口碑好的厌氧胶胶水厂家最新推荐权威榜
  • format函数sql的指南
  • format函数sql的技巧
  • 【URP】Unity渲染层Rendering Layers
  • 2025年评价高的荞麦加工成套设备厂家最新权威推荐排行榜
  • 详细介绍:Flink 的 checkpoint 对 key state 是怎么样存储的?
  • 2025年比较好的陶瓷衬板用户好评厂家排行
  • 零基础学习CMake--第六章:测试与调试——用CTest让项目更可靠6.3 测试报告生成:HTML/XML格式输出与持续集成(CI) - 指南
  • High-quality Surface Reconstruction using Gaussian Surfels 论文阅读 - 实践
  • 2025年评价高的小麦磨面机行业内口碑厂家排行榜
  • 2025年口碑好的销量最好的电动车电池厂家最新热销排行
  • 2025年质量好的深睡记忆棉枕厂家最新TOP实力排行
  • inventor安装失败,如何使用卸载工具,完全彻底删除干净inventor各种残留注册表和文件
  • 2025年靠谱的AB枕芯厂家推荐及选购参考榜
  • 【机器人】RViz中LaserScan的参数信息说明 - 教程
  • 2025年热门的钙粉选粉机厂家最新推荐权威榜
  • format函数sql的实例
  • format函数sql的作用
  • 2025年聚氨酯发泡保温厂家联系电话完整汇总:全国重点企业官方联系方式与高效采购指南
  • 2025年聚氨酯发泡保温厂家联系电话汇总:全国重点企业官方联系方式及工程对接指南
  • 2025年11月全屋智能家居品牌推荐榜单与深度对比分析
  • Flink的checkpoint interval与mini-batch什么区别? - 指南
  • 2025年比较好的煤炭提质选煤设备最新TOP厂家排名
  • 2025年11月劳保鞋品牌排名榜:基于实际使用场景的深度对比报告
  • 2025年11月劳保鞋品牌推荐榜单:多维度对比分析助您选择
  • 2025年质量好的智能干选选煤设备厂家推荐及采购指南
  • 2025年11月留学生回国求职机构推荐:主流机构榜单与选择指南
  • APEX实战第6篇:APEX 如何接入业务数据库用户?
  • 2025年11月留学生回国求职机构推荐榜单及选择指南:一份基于市场数据的客观分析
  • 2025年知名的四球摩擦磨损试验机TOP实力厂家推荐榜