区间反转问题

区间反转问题

本篇随笔浅谈一下算法竞赛中的区间反转问题。


例题 洛谷 P3391 【模板】文艺平衡树

题目传送门

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列。

其中需要提供以下操作:翻转一个区间,例如原有序序列是 5\ 4\ 3\ 2\ 15 4 3 2 1,翻转区间是 [2,4][2,4] 的话,结果是 5\ 2\ 3\ 4\ 15 2 3 4 1。

输入格式

第一行两个正整数 n,mn,m,表示序列长度与操作个数。序列中第 ii 项初始为 ii
接下来 mm 行,每行两个正整数 l,rl,r,表示翻转的区间。

输出格式

输出一行 nn 个正整数,表示原始序列经过 mm 次变换后的结果。

说明/提示

【数据范围】
对于 100%100% 的数据,1 \le n, m \leq 1000001≤n,m≤100000,1 \le l \le r \le n1≤lrn


关于区间反转

对于反转一段区间的操作,我们好像怎么搞都是\(O(N)\)的。

然而对于这道题来讲,\(O(N)\)算法肯定是过不去的。

想要用更优秀的复杂度来做,怎么办呢?

用平衡树来升级,而且必须用Splay。

复杂度达到了均摊\(O(\log N)\)(证明别找我)。

这就已经很优秀了。

那么为什么平衡树的Splay算法能够用均摊\(O(\log N)\)的复杂度来实现区间反转呢?

现在我们用节点编号来建一棵BST。那么根据BST的性质,对于一个针对区间\([L,R]\)的反转操作,我们肯定需要把这个区间变到一个可以方便操作的位置。

那么我们考虑把节点\(L-1\)用旋转splay到根节点,把节点\(R+1\)用旋转splay到根节点的右儿子,根据BST性质,因为我们是使用节点编号建的BST,那么我们就发现:右儿子的左子树就是我们需要操作的区间。这个区间已经被唯一确定下来了。

然后因为我们是用节点编号建的BST,所以直接把每个节点的左右儿子交换就可以。

posted @ 2020-07-31 15:53  Seaway-Fu  阅读(1705)  评论(0编辑  收藏  举报