Loading docs/ds/divide-combine.md +17 −17 Original line number Diff line number Diff line Loading @@ -16,13 +16,13 @@ ### 排列与连续段 **排列**:定义一个 n 阶排列 P 是一个大小为 n 的序列,使得 $P_i$ 取遍 $1,2,\cdots,n$。说得形式化一点,n 阶排列 P 是一个有序集合满足: **排列**:定义一个 $n$ 阶排列 $P$ 是一个大小为 $n$ 的序列,使得 $P_i$ 取遍 $1,2,\cdots,n$。说得形式化一点,$n$ 阶排列 $P$ 是一个有序集合满足: 1. $|P|=n$. 2. $\forall i,P_i\in[1,n]$. 3. $\nexists i,j\in[1,n],P_i=P_j$. **连续段**:对于排列 P,定义连续段 $(P,[l,r])$ 表示一个区间 $[l,r]$,要求 $P_{l\sim r}$ 值域是连续的。说得更形式化一点,对于排列 P,连续段表示一个区间 $[l,r]$ 满足: **连续段**:对于排列 $P$,定义连续段 $(P,[l,r])$ 表示一个区间 $[l,r]$,要求 $P_{l\sim r}$ 值域是连续的。说得更形式化一点,对于排列 $P$,连续段表示一个区间 $[l,r]$ 满足: $$ (\nexists\ x,z\in[l,r],y\notin[l,r],\ P_x<P_y<P_z) Loading @@ -30,7 +30,7 @@ $$ 特别地,当 $l>r$ 时,我们认为这是一个空的连续段,记作 $(P,\varnothing)$。 我们称排列 P 的所有连续段的集合为 $I_P$,并且我们认为 $(P,\varnothing)\in I_P$。 我们称排列 $P$ 的所有连续段的集合为 $I_P$,并且我们认为 $(P,\varnothing)\in I_P$。 ### 连续段的运算 Loading Loading @@ -60,11 +60,11 @@ $$ 其实这个定义全称叫作**本原连续段**。但笔者认为本原段更为简洁。 对于排列 P,我们认为一个本原段 $M$ 表示在集合 $I_P$ 中,不存在与之相交且不包含的连续段。形式化地定义,我们认为 $X\in I_P$ 且满足 $\forall A\in I_P,\ X\cap A= (P,\varnothing)\vee X\subseteq A\vee A\subseteq X$。 对于排列 $P$,我们认为一个本原段 $M$ 表示在集合 $I_P$ 中,不存在与之相交且不包含的连续段。形式化地定义,我们认为 $X\in I_P$ 且满足 $\forall A\in I_P,\ X\cap A= (P,\varnothing)\vee X\subseteq A\vee A\subseteq X$。 所有本原段的集合为 $M_P$. 显而易见,$(P,\varnothing)\in M_P$。 显然,本原段之间只有相离或者包含关系。并且你发现**一个连续段可以由几个互不相交的本原段构成**。最大的本原段就是整个排列本身,它包含了其他所有本原段,因此我们认为本原段可以构成一个树形结构,我们称这个结构为**析合树**。更严格地说,排列 P 的析合树由排列 P 的**所有本原段**组成。 显然,本原段之间只有相离或者包含关系。并且你发现**一个连续段可以由几个互不相交的本原段构成**。最大的本原段就是整个排列本身,它包含了其他所有本原段,因此我们认为本原段可以构成一个树形结构,我们称这个结构为**析合树**。更严格地说,排列 $P$ 的析合树由排列 $P$ 的**所有本原段**组成。 前面干讲这么多的定义,不来点图怎么行。考虑排列 $P=\{9,1,10,3,2,5,7,6,8,4\}$. 它的本原段构成的析合树如下: Loading @@ -76,9 +76,9 @@ $$ 这里我们直接给出定义,稍候再来讨论它的正确性。 1. **值域区间**:对于一个结点 u,用 $[u_l,u_r]$ 表示该结点的值域区间。 2. **儿子序列**:对于析合树上的一个结点 u,假设它的儿子结点是一个**有序**序列,该序列是以值域区间为元素的(单个的数 x 可以理解为 $[x,x]$ 的区间)。我们把这个序列称为儿子序列。记作 $S_u$。 3. **儿子排列**:对于一个儿子序列 $S_u$,把它的元素离散化成正整数后形成的排列称为儿子排列。举个例子,对于结点 $[5,8]$,它的儿子序列为 $\{[5,5],[6,7],[8,8]\}$,那么把区间排序标个号,则它的儿子排列就为 $\{1,2,3\}$;类似的,结点 $[4,8]$ 的儿子排列为 $\{2,1\}$。结点 u 的儿子排列记为 $P_u$。 1. **值域区间**:对于一个结点 $u$,用 $[u_l,u_r]$ 表示该结点的值域区间。 2. **儿子序列**:对于析合树上的一个结点 $u$,假设它的儿子结点是一个**有序**序列,该序列是以值域区间为元素的(单个的数 $x$ 可以理解为 $[x,x]$ 的区间)。我们把这个序列称为儿子序列。记作 $S_u$。 3. **儿子排列**:对于一个儿子序列 $S_u$,把它的元素离散化成正整数后形成的排列称为儿子排列。举个例子,对于结点 $[5,8]$,它的儿子序列为 $\{[5,5],[6,7],[8,8]\}$,那么把区间排序标个号,则它的儿子排列就为 $\{1,2,3\}$;类似的,结点 $[4,8]$ 的儿子排列为 $\{2,1\}$。结点 $u$ 的儿子排列记为 $P_u$。 4. **合点**:我们认为,儿子排列为顺序或者逆序的点为合点。形式化地说,满足 $P_u=\{1,2,\cdots,|S_u|\}$ 或者 $P_u=\{|S_u|,|S_u-1|,\cdots,1\}$ 的点称为合点。**叶子结点没有儿子排列,我们也认为它是合点**。 5. **析点**:不是合点的就是析点。 Loading @@ -86,17 +86,17 @@ $$ ### 析点与合点的性质 析点与合点的命名来源于他们的性质。首先我们有一个非常显然的性质:对于析合树中任何的结点 u,其儿子序列区间的并集就是结点 u 的值域区间。即 $\bigcup_{i=1}^{|S_u|}S_u[i]=[u_l,u_r]$。 析点与合点的命名来源于他们的性质。首先我们有一个非常显然的性质:对于析合树中任何的结点 $u$,其儿子序列区间的并集就是结点 $u$ 的值域区间。即 $\bigcup_{i=1}^{|S_u|}S_u[i]=[u_l,u_r]$。 对于一个合点 u:其儿子序列的任意**子区间**都构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 对于一个合点 $u$:其儿子序列的任意**子区间**都构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 对于一个析点 u:其儿子序列的任意**长度大于 1(这里的长度是指儿子序列中的元素数,不是下标区间的长度)**的子区间都**不**构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 对于一个析点 $u$:其儿子序列的任意**长度大于 1(这里的长度是指儿子序列中的元素数,不是下标区间的长度)**的子区间都**不**构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 合点的性质不难~~口糊~~证明。因为合点的儿子排列要么是顺序,要么是倒序,而值域区间也是首位相接,因此只要是连续的一段子序列(区间)都是一个连续段。 对于析点的性质可能很多读者就不太能理解了:为什么**任意**长度大于 1 的子区间都不构成连续段? 对于析点的性质可能很多读者就不太能理解了:为什么**任意**长度大于 $1$ 的子区间都不构成连续段? 使用反证法。假设对于一个点 u,它的儿子序列中有一个**最长的**区间 $S_u[l\sim r]$ 构成了连续段。那么这个 $A=\bigcup_{i=l}^rS_u[i]\in I_P$,也就意味着 $A$ 是一个本原段!(因为 A 是儿子序列中最长的,因此找不到一个与它相交又不包含的连续段)于是你就没有使用所有的本原段构成这个析合树。矛盾。 使用反证法。假设对于一个点 $u$,它的儿子序列中有一个**最长的**区间 $S_u[l\sim r]$ 构成了连续段。那么这个 $A=\bigcup_{i=l}^rS_u[i]\in I_P$,也就意味着 $A$ 是一个本原段!(因为 $A$ 是儿子序列中最长的,因此找不到一个与它相交又不包含的连续段)于是你就没有使用所有的本原段构成这个析合树。矛盾。 ### 析合树的构造 Loading Loading @@ -139,15 +139,15 @@ $$ 于是我们就维护 $\max_{l\le i\le r}P_i-\min_{l\le i\le r}P_i-(r-l)$,那么要找到一个连续段相当于查询一个最小值! 有了上述思路,不难想到这样的算法。对于增量过程中的当前的 i,我们维护一个数组 $Q$ 表示区间 $[j,i]$ 的极差减长度。即 有了上述思路,不难想到这样的算法。对于增量过程中的当前的 $i$,我们维护一个数组 $Q$ 表示区间 $[j,i]$ 的极差减长度。即 $$ Q_j=\max_{j\le k\le i}P_k-\min_{j\le k\le i}P_k-(i-j),\ \ 0<j<i $$ 现在我们想知道在 $1\sim i-1$ 中是否存在一个最小的 $j$ 使得 $Q_j=0$。这等价于求 $Q_{1\sim i-1}$ 的最小值。求得最小的 j 就是 $L_i$。如果没有,那么 $L_i=i$。 现在我们想知道在 $1\sim i-1$ 中是否存在一个最小的 $j$ 使得 $Q_j=0$。这等价于求 $Q_{1\sim i-1}$ 的最小值。求得最小的 $j$ 就是 $L_i$。如果没有,那么 $L_i=i$。 但是当第 i 次增量结束时,我们需要快速把 $Q$ 数组更新到 i+1 的情况。原本的区间从 $[j,i]$ 变成 $[j,i+1]$,如果 $P_{i+1}>\max$ 或者 $P_{i+1}<\min$ 都会造成 $Q_j$ 发生变化。如何变化?如果 $P_{i+1}>\max$,相当于我们把 $Q_j$ 先减掉 $\max$ 再加上 $P_{i+1}$ 就完成了 $Q_j$ 的更新;$P_{i+1}<\min$ 同理,相当于 $Q_j=Q_j+\min-P_{i+1}$. 但是当第 $i$ 次增量结束时,我们需要快速把 $Q$ 数组更新到 i+1 的情况。原本的区间从 $[j,i]$ 变成 $[j,i+1]$,如果 $P_{i+1}>\max$ 或者 $P_{i+1}<\min$ 都会造成 $Q_j$ 发生变化。如何变化?如果 $P_{i+1}>\max$,相当于我们把 $Q_j$ 先减掉 $\max$ 再加上 $P_{i+1}$ 就完成了 $Q_j$ 的更新;$P_{i+1}<\min$ 同理,相当于 $Q_j=Q_j+\min-P_{i+1}$. 那么如果对于一个区间 $[x,y]$,满足 $P_{x\sim i},P_{x+1\sim i},P_{x+2\sim i},\cdots,P_{y\sim i}$ 的区间 $\max$ 都相同呢?你已经发现了,那么相当于我们在做一个区间加的操作;同理,当 $P_{x\sim i},P_{x+1\sim i},\cdots,P_{y\sim i}$ 的区间 $\min$ 都想同时也是一个区间加的操作。同时,$\max$ 和 $\min$ 的更新是相互独立的, 因此可以各自更新。 Loading @@ -155,7 +155,7 @@ $$ 1. 找到最大的 $j$ 使得 $P_{j}>P_{i+1}$,那么显然,$P_{j+1\sim i}$ 这一段数全部小于 $P_{i+1}$,于是就需要更新 $Q_{j+1\sim i}$ 的最大值。由于 $P_{i},\max(P_i,P_{i-1}),\max(P_i,P_{i-1},P_{i-2}),\cdots,\max(P_i,P_{i-1},\cdots,P_{j+1})$ 是(非严格)单调递增的,因此可以每一段相同的 $\max$ 做相同的更新,即区间加操作。 2. 更新 $\min$ 同理。 3. 把每一个 $Q_j$ 都减 1。因为区间长度加 1。 3. 把每一个 $Q_j$ 都减 $1$。因为区间长度加 $1$。 4. 查询 $L_i$:即查询 $Q$ 的最小值的所在的**下标**。 没错,我们可以使用线段树维护 $Q$!现在还有一个问题:怎么找到相同的一段使得他们的 $\max/\min$ 都相同?使用单调栈维护!维护两个单调栈分别表示 $\max/\min$。那么显然,栈中以相邻两个元素为端点的区间的 $\max/\min$ 是相同的,于是在维护单调栈的时侯顺便更新线段树即可。 Loading Loading
docs/ds/divide-combine.md +17 −17 Original line number Diff line number Diff line Loading @@ -16,13 +16,13 @@ ### 排列与连续段 **排列**:定义一个 n 阶排列 P 是一个大小为 n 的序列,使得 $P_i$ 取遍 $1,2,\cdots,n$。说得形式化一点,n 阶排列 P 是一个有序集合满足: **排列**:定义一个 $n$ 阶排列 $P$ 是一个大小为 $n$ 的序列,使得 $P_i$ 取遍 $1,2,\cdots,n$。说得形式化一点,$n$ 阶排列 $P$ 是一个有序集合满足: 1. $|P|=n$. 2. $\forall i,P_i\in[1,n]$. 3. $\nexists i,j\in[1,n],P_i=P_j$. **连续段**:对于排列 P,定义连续段 $(P,[l,r])$ 表示一个区间 $[l,r]$,要求 $P_{l\sim r}$ 值域是连续的。说得更形式化一点,对于排列 P,连续段表示一个区间 $[l,r]$ 满足: **连续段**:对于排列 $P$,定义连续段 $(P,[l,r])$ 表示一个区间 $[l,r]$,要求 $P_{l\sim r}$ 值域是连续的。说得更形式化一点,对于排列 $P$,连续段表示一个区间 $[l,r]$ 满足: $$ (\nexists\ x,z\in[l,r],y\notin[l,r],\ P_x<P_y<P_z) Loading @@ -30,7 +30,7 @@ $$ 特别地,当 $l>r$ 时,我们认为这是一个空的连续段,记作 $(P,\varnothing)$。 我们称排列 P 的所有连续段的集合为 $I_P$,并且我们认为 $(P,\varnothing)\in I_P$。 我们称排列 $P$ 的所有连续段的集合为 $I_P$,并且我们认为 $(P,\varnothing)\in I_P$。 ### 连续段的运算 Loading Loading @@ -60,11 +60,11 @@ $$ 其实这个定义全称叫作**本原连续段**。但笔者认为本原段更为简洁。 对于排列 P,我们认为一个本原段 $M$ 表示在集合 $I_P$ 中,不存在与之相交且不包含的连续段。形式化地定义,我们认为 $X\in I_P$ 且满足 $\forall A\in I_P,\ X\cap A= (P,\varnothing)\vee X\subseteq A\vee A\subseteq X$。 对于排列 $P$,我们认为一个本原段 $M$ 表示在集合 $I_P$ 中,不存在与之相交且不包含的连续段。形式化地定义,我们认为 $X\in I_P$ 且满足 $\forall A\in I_P,\ X\cap A= (P,\varnothing)\vee X\subseteq A\vee A\subseteq X$。 所有本原段的集合为 $M_P$. 显而易见,$(P,\varnothing)\in M_P$。 显然,本原段之间只有相离或者包含关系。并且你发现**一个连续段可以由几个互不相交的本原段构成**。最大的本原段就是整个排列本身,它包含了其他所有本原段,因此我们认为本原段可以构成一个树形结构,我们称这个结构为**析合树**。更严格地说,排列 P 的析合树由排列 P 的**所有本原段**组成。 显然,本原段之间只有相离或者包含关系。并且你发现**一个连续段可以由几个互不相交的本原段构成**。最大的本原段就是整个排列本身,它包含了其他所有本原段,因此我们认为本原段可以构成一个树形结构,我们称这个结构为**析合树**。更严格地说,排列 $P$ 的析合树由排列 $P$ 的**所有本原段**组成。 前面干讲这么多的定义,不来点图怎么行。考虑排列 $P=\{9,1,10,3,2,5,7,6,8,4\}$. 它的本原段构成的析合树如下: Loading @@ -76,9 +76,9 @@ $$ 这里我们直接给出定义,稍候再来讨论它的正确性。 1. **值域区间**:对于一个结点 u,用 $[u_l,u_r]$ 表示该结点的值域区间。 2. **儿子序列**:对于析合树上的一个结点 u,假设它的儿子结点是一个**有序**序列,该序列是以值域区间为元素的(单个的数 x 可以理解为 $[x,x]$ 的区间)。我们把这个序列称为儿子序列。记作 $S_u$。 3. **儿子排列**:对于一个儿子序列 $S_u$,把它的元素离散化成正整数后形成的排列称为儿子排列。举个例子,对于结点 $[5,8]$,它的儿子序列为 $\{[5,5],[6,7],[8,8]\}$,那么把区间排序标个号,则它的儿子排列就为 $\{1,2,3\}$;类似的,结点 $[4,8]$ 的儿子排列为 $\{2,1\}$。结点 u 的儿子排列记为 $P_u$。 1. **值域区间**:对于一个结点 $u$,用 $[u_l,u_r]$ 表示该结点的值域区间。 2. **儿子序列**:对于析合树上的一个结点 $u$,假设它的儿子结点是一个**有序**序列,该序列是以值域区间为元素的(单个的数 $x$ 可以理解为 $[x,x]$ 的区间)。我们把这个序列称为儿子序列。记作 $S_u$。 3. **儿子排列**:对于一个儿子序列 $S_u$,把它的元素离散化成正整数后形成的排列称为儿子排列。举个例子,对于结点 $[5,8]$,它的儿子序列为 $\{[5,5],[6,7],[8,8]\}$,那么把区间排序标个号,则它的儿子排列就为 $\{1,2,3\}$;类似的,结点 $[4,8]$ 的儿子排列为 $\{2,1\}$。结点 $u$ 的儿子排列记为 $P_u$。 4. **合点**:我们认为,儿子排列为顺序或者逆序的点为合点。形式化地说,满足 $P_u=\{1,2,\cdots,|S_u|\}$ 或者 $P_u=\{|S_u|,|S_u-1|,\cdots,1\}$ 的点称为合点。**叶子结点没有儿子排列,我们也认为它是合点**。 5. **析点**:不是合点的就是析点。 Loading @@ -86,17 +86,17 @@ $$ ### 析点与合点的性质 析点与合点的命名来源于他们的性质。首先我们有一个非常显然的性质:对于析合树中任何的结点 u,其儿子序列区间的并集就是结点 u 的值域区间。即 $\bigcup_{i=1}^{|S_u|}S_u[i]=[u_l,u_r]$。 析点与合点的命名来源于他们的性质。首先我们有一个非常显然的性质:对于析合树中任何的结点 $u$,其儿子序列区间的并集就是结点 $u$ 的值域区间。即 $\bigcup_{i=1}^{|S_u|}S_u[i]=[u_l,u_r]$。 对于一个合点 u:其儿子序列的任意**子区间**都构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 对于一个合点 $u$:其儿子序列的任意**子区间**都构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 对于一个析点 u:其儿子序列的任意**长度大于 1(这里的长度是指儿子序列中的元素数,不是下标区间的长度)**的子区间都**不**构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 对于一个析点 $u$:其儿子序列的任意**长度大于 1(这里的长度是指儿子序列中的元素数,不是下标区间的长度)**的子区间都**不**构成一个**连续段**。形式化地说,对于 $S_u[l\sim r]$,有 $\bigcup_{i=l}^rS_u[i]\in I_P$。 合点的性质不难~~口糊~~证明。因为合点的儿子排列要么是顺序,要么是倒序,而值域区间也是首位相接,因此只要是连续的一段子序列(区间)都是一个连续段。 对于析点的性质可能很多读者就不太能理解了:为什么**任意**长度大于 1 的子区间都不构成连续段? 对于析点的性质可能很多读者就不太能理解了:为什么**任意**长度大于 $1$ 的子区间都不构成连续段? 使用反证法。假设对于一个点 u,它的儿子序列中有一个**最长的**区间 $S_u[l\sim r]$ 构成了连续段。那么这个 $A=\bigcup_{i=l}^rS_u[i]\in I_P$,也就意味着 $A$ 是一个本原段!(因为 A 是儿子序列中最长的,因此找不到一个与它相交又不包含的连续段)于是你就没有使用所有的本原段构成这个析合树。矛盾。 使用反证法。假设对于一个点 $u$,它的儿子序列中有一个**最长的**区间 $S_u[l\sim r]$ 构成了连续段。那么这个 $A=\bigcup_{i=l}^rS_u[i]\in I_P$,也就意味着 $A$ 是一个本原段!(因为 $A$ 是儿子序列中最长的,因此找不到一个与它相交又不包含的连续段)于是你就没有使用所有的本原段构成这个析合树。矛盾。 ### 析合树的构造 Loading Loading @@ -139,15 +139,15 @@ $$ 于是我们就维护 $\max_{l\le i\le r}P_i-\min_{l\le i\le r}P_i-(r-l)$,那么要找到一个连续段相当于查询一个最小值! 有了上述思路,不难想到这样的算法。对于增量过程中的当前的 i,我们维护一个数组 $Q$ 表示区间 $[j,i]$ 的极差减长度。即 有了上述思路,不难想到这样的算法。对于增量过程中的当前的 $i$,我们维护一个数组 $Q$ 表示区间 $[j,i]$ 的极差减长度。即 $$ Q_j=\max_{j\le k\le i}P_k-\min_{j\le k\le i}P_k-(i-j),\ \ 0<j<i $$ 现在我们想知道在 $1\sim i-1$ 中是否存在一个最小的 $j$ 使得 $Q_j=0$。这等价于求 $Q_{1\sim i-1}$ 的最小值。求得最小的 j 就是 $L_i$。如果没有,那么 $L_i=i$。 现在我们想知道在 $1\sim i-1$ 中是否存在一个最小的 $j$ 使得 $Q_j=0$。这等价于求 $Q_{1\sim i-1}$ 的最小值。求得最小的 $j$ 就是 $L_i$。如果没有,那么 $L_i=i$。 但是当第 i 次增量结束时,我们需要快速把 $Q$ 数组更新到 i+1 的情况。原本的区间从 $[j,i]$ 变成 $[j,i+1]$,如果 $P_{i+1}>\max$ 或者 $P_{i+1}<\min$ 都会造成 $Q_j$ 发生变化。如何变化?如果 $P_{i+1}>\max$,相当于我们把 $Q_j$ 先减掉 $\max$ 再加上 $P_{i+1}$ 就完成了 $Q_j$ 的更新;$P_{i+1}<\min$ 同理,相当于 $Q_j=Q_j+\min-P_{i+1}$. 但是当第 $i$ 次增量结束时,我们需要快速把 $Q$ 数组更新到 i+1 的情况。原本的区间从 $[j,i]$ 变成 $[j,i+1]$,如果 $P_{i+1}>\max$ 或者 $P_{i+1}<\min$ 都会造成 $Q_j$ 发生变化。如何变化?如果 $P_{i+1}>\max$,相当于我们把 $Q_j$ 先减掉 $\max$ 再加上 $P_{i+1}$ 就完成了 $Q_j$ 的更新;$P_{i+1}<\min$ 同理,相当于 $Q_j=Q_j+\min-P_{i+1}$. 那么如果对于一个区间 $[x,y]$,满足 $P_{x\sim i},P_{x+1\sim i},P_{x+2\sim i},\cdots,P_{y\sim i}$ 的区间 $\max$ 都相同呢?你已经发现了,那么相当于我们在做一个区间加的操作;同理,当 $P_{x\sim i},P_{x+1\sim i},\cdots,P_{y\sim i}$ 的区间 $\min$ 都想同时也是一个区间加的操作。同时,$\max$ 和 $\min$ 的更新是相互独立的, 因此可以各自更新。 Loading @@ -155,7 +155,7 @@ $$ 1. 找到最大的 $j$ 使得 $P_{j}>P_{i+1}$,那么显然,$P_{j+1\sim i}$ 这一段数全部小于 $P_{i+1}$,于是就需要更新 $Q_{j+1\sim i}$ 的最大值。由于 $P_{i},\max(P_i,P_{i-1}),\max(P_i,P_{i-1},P_{i-2}),\cdots,\max(P_i,P_{i-1},\cdots,P_{j+1})$ 是(非严格)单调递增的,因此可以每一段相同的 $\max$ 做相同的更新,即区间加操作。 2. 更新 $\min$ 同理。 3. 把每一个 $Q_j$ 都减 1。因为区间长度加 1。 3. 把每一个 $Q_j$ 都减 $1$。因为区间长度加 $1$。 4. 查询 $L_i$:即查询 $Q$ 的最小值的所在的**下标**。 没错,我们可以使用线段树维护 $Q$!现在还有一个问题:怎么找到相同的一段使得他们的 $\max/\min$ 都相同?使用单调栈维护!维护两个单调栈分别表示 $\max/\min$。那么显然,栈中以相邻两个元素为端点的区间的 $\max/\min$ 是相同的,于是在维护单调栈的时侯顺便更新线段树即可。 Loading