简单数据结构做题记录

CF526F Pudding Monsters

典题,发现这本质上是一个一维问题,一个区间合法当且仅当 maxmin=rl,枚举右端点维护左端点的变化量,用两个单调栈维护到 r 的最大最小,用线段树维护区间最小值及其个数,由于 [r,r] 满足条件且 maxminr+l0,因此每次累加最小值个数即可。

时间复杂度 O(nlogn)

CF603E Pastoral Oddities

先找“每个点度数均为奇数”的充要条件,容易发现是“加入所有边后不存在奇连通块”。

证明是简单的。

充分性:显然对于每个连通块独立,随便找一个点当根求出一棵生成树,自底向上考虑每个非根的点,若儿子度数为偶数则加上其与父亲的连边,否则删去这条边,此时除了根所在连通块都满足条件,同时注意到总度数为偶数,有奇数个点的度数为奇数,必然根的度数也为奇数。

必要性:若存在奇数连通块,则要求总度数为奇数,无论怎么删去边,总度数都为奇数,显然非法。### CF526F Pudding Monsters

典题,发现这本质上是一个一维问题,一个区间合法当且仅当 maxmin=rl,枚举右端点维护左端点的变化量,用两个单调栈维护到 r 的最大最小,用线段树维护区间最小值及其个数,由于 [r,r] 满足条件且 maxminr+l0,因此每次累加最小值个数即可。

时间复杂度 O(nlogn)

CF603E Pastoral Oddities

先找“每个点度数均为奇数”的充要条件,容易发现是“加入所有边后不存在奇连通块”。

证明是简单的。

充分性:显然对于每个连通块独立,随便找一个点当根求出一棵生成树,自底向上考虑每个非根的点,若儿子度数为偶数则加上其与父亲的连边,否则删去这条边,此时除了根所在连通块都满足条件,同时注意到总度数为偶数,有奇数个点的度数为奇数,必然根的度数也为奇数。

必要性:若存在奇数连通块,则要求总度数为奇数,无论怎么删去边,总度数都为奇数,显然非法。

注意到能合并就合并是最优的,因为无论是偶 + 偶,奇 + 偶,奇 + 奇都不会增加奇数个数,于是对于单次询问,可以考虑类似 Kruskal 的过程得到答案。

注意到答案单调不升,可以考虑整体二分。

注意到每次加边的变化只有当两边子树都是奇数才有用,可以直接上 LCT。

注意到若我们从后往前处理,将边集排序后维护一个指针表示当前答案,对于已经加入答案的边而言我们需要在某一时间段维护其合法范围,就可以直接线段树分治维护。

时间复杂度 O(nlognlogm)

CF1446D2 Frequency Problem (Hard Version)

容易用调整法证明两个答案其中一个为全局众数,设为 maj

暴力就是再枚举另一个元素 x,将 x 看做 1,maj 看做 -1,答案就是最长的和为 0 的段。

还有一个暴力:直接枚举出现次数 cnt,双指针枚举 maj 的第一次出现位置,对 [l,r] 的这些数开桶记录出现次数为 i 的有多少个,当 最大值恰为 cnt 且个数 2 则存在。

结合上面两个算法,考虑根号分治,对于 occi>B 的数直接 O(n) 算,否则直接枚举 cnt,也可以 O(n) 算。

时间复杂度 O(nn)

CF997E Good Subsegments

显然就是 CF526F 的加强版。考虑记录 maxmin(rl) 最小值,最小值个数,用历史线段树维护之。

每次将右端点扩展 1 时,需要对所有 ti=0 的位置 sisi+1,直接打一个只对最小值生效的 tag 即可。

CF319E Ping-Pong

注意到若两个区间相交但不包含,则二者双向可达。若一个大的包含一个小的,则只能从大区间到小区间。

不妨直接将第一类区间用并查集合并看做一个点,容易发现每次询问最多走一次大区间到小区间。对于一次从 x 走向 y 的询问,若 x,y 已经在同一连通块或 x,y 为包含关系则可以到达。

接下来考虑如何合并只相交的线段,注意到插入的线段长度单调不降,考虑将一个线段 [l,r] 加入 [l+1,r1] 的集合中,每次查询 lr 中的元素合并,同时剩下的线段没有用,并清空集合变成合并后的大集合。

时间复杂度 O(nlognα(n))

CF1163F Indecisive Taxi Fee

CF436F Banners

前面 bicw×c 是平凡的,对于后面的 bi<c,aipp 不妨扫描线,每次加入若干个 ai,对于 p 开线段树维护答案。则每次等价于将所有 pai 的位置加上 y=x 的函数。问题变为:

维护一个初始全 0 的序列,支持对一个前缀加上一个一次函数,询问全局 max

很可惜李超树并不能维护一次函数相加后的 min,考虑分块,每块内部记录 tg 和初始值 ai,则 i 的贡献是 ai+tg×i,根据经典结论将每个 i 看做 (i,ai),则只有上凸包中的点有用,由于每次斜率单减直接开指针扫,散块直接暴力重构。

时间复杂度 O(nn)

CF793F Julia the snail

先离线扫,将 [li,ri] 挂在 ri,用线段树对每个 l 维护初始在 l,在经过所有不超过 r 的绳子能到达的最大高度,对于一个 [li,ri] 而言,等价于将所有 i[1,li],aili,aimax(ai,ri)

由于 r 是单调枚举的,也可以看做 air,即区间 某值的赋值。

使用吉司机线段树(然鹅并不会势能分析) 维护。

CF1178G The Awesomest Vertex

显然 |b| 是常数,问题变成每个点是 a|x|(a0),每次区间 x 加一个正数 v,求区间最大。

显然不能 polylog,考虑分块,首先 |x|=max(x,x),维护 xx 两次取 max 即可。

此时问题变成 CF436E。

CF773E Blog Post Rating

手玩发现 F 一定是先单减后不降。

F 第一次不降的位置 i 满足 aii,对于剩下的位置有 fi=min(fi1+1,ai)。答案是 fn

用值域线段树维护所有已经加入的位置,每次线段树二分先找到第一个分界点 p,在 p1 的答案是 (p1)

fn 的柿子拆开,ans=min(an,an1+1,,ap+np,np+1(p1))

再维护 app 的区间 min,每次查询就变成了后缀 min

时间复杂度 O(nlogn)

CF765F Souvenirs

不妨设 j<i,ai<aj,考虑哪些二元组 (i,j) 可能成为最优决策:必然是单调递增的单调栈中所有 aij。当然,不能直接枚举所有 j,但发现若 k<j,ak<aj,ajak<akai,则该部分已经在 (k,j) 算过了,所以合法的 k 必然满足 akai<ajakak<ai+aj2

出现了值域减半,因此总共的 k 最多有 nlogn 个,用一个线段树找一下即可,然后用树状数组维护一下二维数点。

CF679E Bear and Bad Powers of 42

先粗略估一下 aiqV,而 4210>1014,因此合法的 power 极少,直观上应该是一个势能分析。

考虑记录每个 ai 与其最近的 42 幂次的距离,操作 3 相当于若区间最小值 = 0 则不断做一个区间减法,减完后若 <0 则暴力更新新的距离。则花费在每个数上的复杂度为 O(log42qV×logn)

现在加上区间赋值,感觉用 ODT 复杂度摊着摊着就对了!但不能直接用 ODT 来表示连续段,因为这会使线段树区间发生变化。

考虑直接在线段树上区间赋值,这等价于将每个连续段再拆成了 logn 个段,此时再考察操作 3:

  • 若线段树区间存在赋值标记,更新赋值标记重新计算距离。
  • 否则不断递归直到区间最小值 x 或者到达叶子节点。

时间复杂度 O(nlog42qV×logn)

CF571D Campus

离线,对每次集合的合并分别建出 Kruskal 重构树。对于第 5 类询问 x,在第二类集合中找到最后一次涉及到 x 的置 0 操作,离线后就变成一个前缀查询。

第 3 类操作等价于在 Kruskal 上子树加,用树状数组维护即可。

时间复杂度 O(nlogn)

CF407E k-d-sequence

区间 [l,r] 满足条件当且仅当:

  • 所有数 modd 同余。
  • 不存在重复元素。
  • maxmind(rl)k

先找到 modd 同余的所有极长区间,用一些简单套路维护。

时间复杂度 O(nlogn)

注意特判 d=0

CF700D Huffman Coding on Segment

首先转化题意,可以发现这就是哈夫曼编码,设 occi 表示 i 出现次数,问题即求 [l,r] 中所有 i 构成的最小的 Huffman 树带权深度,即 iocci×di

而求解 Huffman 树的算法就是合并果子,开一个小根堆,每次取出最小的两个元素,答案累加和,再加入他们的和。

先用莫队求出 occi,由于不同的 occi 最多 O(n) 个,一个想法是开一个链表记录所有 >0occi,设 oci 表示 occp=ip 的个数,从小到大合并。若存在奇数个则额外用一个变量记录,可以通过。

还有一种想法是再根分一波,设 B=n,对于 iB 暴力套用第一个做法,若合并出 >B 的数则加入小根堆。对于 >B 的数直接加入小根堆。然后就真的按照合并果子模拟。

时间复杂度 O(nn)O(nnlogn)

CF633H Fibonacci-ish II

暴力 O(n2) 都能过,不懂为什么开 n=30000

显然莫队 + 树状数组, O(nnlogn)

CF453E Little Pony and Lord Tirek

注意到每次查询区间后马上推平,可以想到 ODT。设 (l,r,v) 表示区间 [l,r] 推平的时刻都是 v,则每次考虑一段区间的贡献时,若是第一次推平,贡献为 min(mi,si+tri),左边取最值时 ms+trtmsr, 贡献为 mi,否则贡献为 si+tri 。可以用主席树维护。但稍加思索发现,反正都是第一次操作,总的个数只有 n 个,暴力就行了。

否则贡献为 min(mi,(tv)ri),同理分析可得 tmr+v 时取到 mi,还是可以用主席树维护之。

时间复杂度 O(nlogn)

模拟赛有个加强版:从区间询问变成树上距离 x 不超过 d 的子树内的答案,做法就是先按照 dfs 序排序后分块,每块内部再按照深度排序,这样每次查询就是区间的形式,对应到一个块内就是一段前缀 split 查询,散块暴力。时间复杂度 O(nnlogn),按照 @Salieri 的说法,可以先把 ODT 换成栈减少 set 的 log,而每次查询是一个静态的二维偏序问题,总共有 nn 个,差分后对每个块离线扫一遍,再加上亿点点的细节就可以做到 O(nn),而且应该常数很小。

CF536E Tavas on the Path

讲询问离线按照 l 升序排序,相当于每次把一些边从 1 变成 0。然后直接树剖,每个节点维护最靠左的连续段颜色及长度,最靠右区间颜色及长度,非边界的答案,每次讨论一下 push_up 就好了。

时间复杂度 O(nlog2n)

CF855F Nagini

用线段树加入同时存在 >0<0 的位置,可以对正负数开两个线段树在线段树上二分得到。

然后用 segment tree beats 维护正负数区间取 min 即可,注意只统计加入的位置。

每个位置最多被加入一次,时间复杂度 O(nlogn)

CF1332G No Monotone Triples

根据 Diliworth 定理,当 n5 时必然存在单调三元组(当然可以通过枚举直接得到)。

分类讨论 n=2,3,4 的情况。

n=2 当且仅当 [l,r] 为单调区间。

n=3 ,对每个 i 找到左边最大的 >aij,右边最小的 >aik;或者左边最大的 <aij,右边最小的 <aik。显然 (j,i,k) 是一组合法方案。

n=4 当且仅当两个端点都不是最值,考虑枚举最右端的 x,考虑找到最优秀的最大和最小值,容易发现 p2,p3 只能分别在前缀最大 / 最小单调栈中取到。

p4 一定不在任何一个单调栈内,否则它会成为最值。

在两个单调栈上二分出第一个 >ax<ax 的位置,设为 y,z,找到 max(y,z) 之后的第一个 “空隙”,即不在任何一个单调栈中的元素,这一定是最靠左的 p4p3 就取 p4 之前的第一个元素,p2 同理。

找出这些 (p1,p4) 后离线二维数点即可。找 p2,p3,p4 的过程可以在单调栈上二分和线段树上二分。时间复杂度 O(nlogn)

CF1476G Minimum Difference

和出现次数有关的问题,根据经典结论不同出现的个数是 O(n) 的性质,且本题恰好也只要求出现次数的次数,于是只要我们把区间的这些出现次数的出现次数找出来,双指针扫一遍就是答案。

显然可以用带修莫队维护,由于要支持 O(1) 加入删除,可以用链表维护,最后在查询时提取这些出现次数排序即可。时间复杂度 O(nm2/3)+mnlogn)。 可以用基数排序优化,但是没有必要。

CF960H Santa's Gift

拆询问,即 Si2×bx2SibxC2,显然只需要对每个颜色维护 Si2,Si 即可,树剖解决。

CF792F Mages and Monsters

观察到问题类似线性规划,设 xi 表示第 i 个法术的使用时间,则:

mini=1nxi

满足约束:

i=1nxivihi=1nxicimi=1nxi(ci)m

考虑其对偶变量,设为 A,B,则满足:

maxAhBm

满足约束:

viAciB1  i[1,n]

由于线性规划对于每个变量都是凸的,于是可以三分 B,变成 A1vi+civiB,可以用李超线段树求出 A 的范围。

显然根据定义,A,B 非负,因此 A 直接取到上界一定是最优的,然后再判断 AhBmt 的关系即可。

CF720D Slaom

由于对于所有障碍经过方式(从上 / 左经过)相同的方案是相同的,考虑找到一个关键路径统计答案。不妨直接找最低路径统计(在相同方案中所有点都是最低的)。

fi,j 表示目前在 (i,j) 的方案,考虑如何转移。

没有障碍时显然 fi,j=fi1,j

否则假设障碍在 [l,r],之前在 [l,r] 的贡献都应该统计到 r+1 上,但是不止于此,设 <l 的右端点为 p,则 [p+1,r] 这一段区间的 fi1,j 都可以贡献到 fi,r+1。用线段树维护,支持区间查询,赋值即可。

至于如何找到 p,将矩形类似扫描线挂在对应端点,用一个 set 实时维护当前的线段即可。

注意最后的答案要找到最后一个区间 [l,r],询问 [r+1,m] 的答案。

CF1344E Train Tracks

首先并不是要等到火车完全走完边后再切换,而是花费 1 时间切换后就已经不用管然后可以继续切换。先考虑如何写暴力:对于同一个点而言,若在 t1 时刻存在经过该点的火车,t2 时刻又存在,则在 [t1+1,t2] 时刻必然要切换一次 x。把所有形如:在 [l,r] 中至少有一次切换某点的限制找出来后,问题变成:

有若干个区间 [l,r],每秒可以选择一个未标记的且 ltr 的区间进行标记,问是否能把所有区间标记

显然可以贪心,维护一个小根堆,每次把 r 最小的弹出,若 r<t 则报告无解。

考虑如何找到这些区间,注意到“切换儿子并更新当且点最后一次标记时间戳“ 类似 access。于是用 lct 维护,每次 access x 时,如果有儿子,就表示 x 要切换一次,显然总切换次数是 O(nlogn) 的,且设 x 深度为 d,上一次覆盖标记为 lst,就要在 [lst+dx+1,cur+dx] 切换一次,把这 O(nlogn) 条路径找出来后贪心即可。

时间复杂度 O(nlog2n)

注意到能合并就合并是最优的,因为无论是偶 + 偶,奇 + 偶,奇 + 奇都不会增加奇数个数,于是对于单次询问,可以考虑类似 Kruskal 的过程得到答案。

注意到答案单调不升,可以考虑整体二分。

注意到每次加边的变化只有当两边子树都是奇数才有用,可以直接上 LCT。

注意到若我们从后往前处理,将边集排序后维护一个指针表示当前答案,对于已经加入答案的边而言我们需要在某一时间段维护其合法范围,就可以直接线段树分治维护。

时间复杂度 O(nlognlogm)

CF1446D2 Frequency Problem (Hard Version)

容易用调整法证明两个答案其中一个为全局众数,设为 maj

暴力就是再枚举另一个元素 x,将 x 看做 1,maj 看做 -1,答案就是最长的和为 0 的段。

还有一个暴力:直接枚举出现次数 cnt,双指针枚举 maj 的第一次出现位置,对 [l,r] 的这些数开桶记录出现次数为 i 的有多少个,当 最大值恰为 cnt 且个数 2 则存在。

结合上面两个算法,考虑根号分治,对于 occi>B 的数直接 O(n) 算,否则直接枚举 cnt,也可以 O(n) 算。

时间复杂度 O(nn)

CF997E Good Subsegments

显然就是 CF526F 的加强版。考虑记录 maxmin(rl) 最小值,最小值个数,用历史线段树维护之。

每次将右端点扩展 1 时,需要对所有 ti=0 的位置 sisi+1,直接打一个只对最小值生效的 tag 即可。

CF319E Ping-Pong

注意到若两个区间相交但不包含,则二者双向可达。若一个大的包含一个小的,则只能从大区间到小区间。

不妨直接将第一类区间用并查集合并看做一个点,容易发现每次询问最多走一次大区间到小区间。对于一次从 x 走向 y 的询问,若 x,y 已经在同一连通块或 x,y 为包含关系则可以到达。

接下来考虑如何合并只相交的线段,注意到插入的线段长度单调不降,考虑将一个线段 [l,r] 加入 [l+1,r1] 的集合中,每次查询 lr 中的元素合并,同时剩下的线段没有用,并清空集合变成合并后的大集合。

时间复杂度 O(nlognα(n))

CF1163F Indecisive Taxi Fee

CF436F Banners

前面 bicw×c 是平凡的,对于后面的 bi<c,aipp 不妨扫描线,每次加入若干个 ai,对于 p 开线段树维护答案。则每次等价于将所有 pai 的位置加上 y=x 的函数。问题变为:

维护一个初始全 0 的序列,支持对一个前缀加上一个一次函数,询问全局 max

很可惜李超树并不能维护一次函数相加后的 min,考虑分块,每块内部记录 tg 和初始值 ai,则 i 的贡献是 ai+tg×i,根据经典结论将每个 i 看做 (i,ai),则只有上凸包中的点有用,由于每次斜率单减直接开指针扫,散块直接暴力重构。

时间复杂度 O(nn)

CF793F Julia the snail

先离线扫,将 [li,ri] 挂在 ri,用线段树对每个 l 维护初始在 l,在经过所有不超过 r 的绳子能到达的最大高度,对于一个 [li,ri] 而言,等价于将所有 i[1,li],aili,aimax(ai,ri)

由于 r 是单调枚举的,也可以看做 air,即区间 某值的赋值。

使用吉司机线段树(然鹅并不会势能分析) 维护。

CF1178G The Awesomest Vertex

显然 |b| 是常数,问题变成每个点是 a|x|(a0),每次区间 x 加一个正数 v,求区间最大。

显然不能 polylog,考虑分块,首先 |x|=max(x,x),维护 xx 两次取 max 即可。

此时问题变成 CF436E。

CF773E Blog Post Rating

手玩发现 F 一定是先单减后不降。

F 第一次不降的位置 i 满足 aii,对于剩下的位置有 fi=min(fi1+1,ai)。答案是 fn

用值域线段树维护所有已经加入的位置,每次线段树二分先找到第一个分界点 p,在 p1 的答案是 (p1)

fn 的柿子拆开,ans=min(an,an1+1,,ap+np,np+1(p1))

再维护 app 的区间 min,每次查询就变成了后缀 min

时间复杂度 O(nlogn)

CF765F Souvenirs

不妨设 j<i,ai<aj,考虑哪些二元组 (i,j) 可能成为最优决策:必然是单调递增的单调栈中所有 aij。当然,不能直接枚举所有 j,但发现若 k<j,ak<aj,ajak<akai,则该部分已经在 (k,j) 算过了,所以合法的 k 必然满足 akai<ajakak<ai+aj2

出现了值域减半,因此总共的 k 最多有 nlogn 个,用一个线段树找一下即可,然后用树状数组维护一下二维数点。

CF679E Bear and Bad Powers of 42

先粗略估一下 aiqV,而 4210>1014,因此合法的 power 极少,直观上应该是一个势能分析。

考虑记录每个 ai 与其最近的 42 幂次的距离,操作 3 相当于若区间最小值 = 0 则不断做一个区间减法,减完后若 <0 则暴力更新新的距离。则花费在每个数上的复杂度为 O(log42qV×logn)

现在加上区间赋值,感觉用 ODT 复杂度摊着摊着就对了!但不能直接用 ODT 来表示连续段,因为这会使线段树区间发生变化。

考虑直接在线段树上区间赋值,这等价于将每个连续段再拆成了 logn 个段,此时再考察操作 3:

  • 若线段树区间存在赋值标记,更新赋值标记重新计算距离。
  • 否则不断递归直到区间最小值 x 或者到达叶子节点。

时间复杂度 O(nlog42qV×logn)

CF571D Campus

离线,对每次集合的合并分别建出 Kruskal 重构树。对于第 5 类询问 x,在第二类集合中找到最后一次涉及到 x 的置 0 操作,离线后就变成一个前缀查询。

第 3 类操作等价于在 Kruskal 上子树加,用树状数组维护即可。

时间复杂度 O(nlogn)

CF407E k-d-sequence

区间 [l,r] 满足条件当且仅当:

  • 所有数 modd 同余。
  • 不存在重复元素。
  • maxmind(rl)k

先找到 modd 同余的所有极长区间,用一些简单套路维护。

时间复杂度 O(nlogn)

注意特判 d=0

CF700D Huffman Coding on Segment

首先转化题意,可以发现这就是哈夫曼编码,设 occi 表示 i 出现次数,问题即求 [l,r] 中所有 i 构成的最小的 Huffman 树带权深度,即 iocci×di

而求解 Huffman 树的算法就是合并果子,开一个小根堆,每次取出最小的两个元素,答案累加和,再加入他们的和。

先用莫队求出 occi,由于不同的 occi 最多 O(n) 个,一个想法是开一个链表记录所有 >0occi,设 oci 表示 occp=ip 的个数,从小到大合并。若存在奇数个则额外用一个变量记录,可以通过。

还有一种想法是再根分一波,设 B=n,对于 iB 暴力套用第一个做法,若合并出 >B 的数则加入小根堆。对于 >B 的数直接加入小根堆。然后就真的按照合并果子模拟。

时间复杂度 O(nn)O(nnlogn)

CF633H Fibonacci-ish II

暴力 O(n2) 都能过,不懂为什么开 n=30000

显然莫队 + 树状数组, O(nnlogn)

CF453E Little Pony and Lord Tirek

注意到每次查询区间后马上推平,可以想到 ODT。设 (l,r,v) 表示区间 [l,r] 推平的时刻都是 v,则每次考虑一段区间的贡献时,若是第一次推平,贡献为 min(mi,si+tri),左边取最值时 ms+trtmsr, 贡献为 mi,否则贡献为 si+tri 。可以用主席树维护。但稍加思索发现,反正都是第一次操作,总的个数只有 n 个,暴力就行了。

否则贡献为 min(mi,(tv)ri),同理分析可得 tmr+v 时取到 mi,还是可以用主席树维护之。

时间复杂度 O(nlogn)

模拟赛有个加强版:从区间询问变成树上距离 x 不超过 d 的子树内的答案,做法就是先按照 dfs 序排序后分块,每块内部再按照深度排序,这样每次查询就是区间的形式,对应到一个块内就是一段前缀 split 查询,散块暴力。时间复杂度 O(nnlogn),按照 @Salieri 的说法,可以先把 ODT 换成栈减少 set 的 log,而每次查询是一个静态的二维偏序问题,总共有 nn 个,差分后对每个块离线扫一遍,再加上亿点点的细节就可以做到 O(nn),而且应该常数很小。

CF536E Tavas on the Path

讲询问离线按照 l 升序排序,相当于每次把一些边从 1 变成 0。然后直接树剖,每个节点维护最靠左的连续段颜色及长度,最靠右区间颜色及长度,非边界的答案,每次讨论一下 push_up 就好了。

时间复杂度 O(nlog2n)

CF855F Nagini

用线段树加入同时存在 >0<0 的位置,可以对正负数开两个线段树在线段树上二分得到。

然后用 segment tree beats 维护正负数区间取 min 即可,注意只统计加入的位置。

每个位置最多被加入一次,时间复杂度 O(nlogn)

CF1332G No Monotone Triples

根据 Diliworth 定理,当 n5 时必然存在单调三元组(当然可以通过枚举直接得到)。

分类讨论 n=2,3,4 的情况。

n=2 当且仅当 [l,r] 为单调区间。

n=3 ,对每个 i 找到左边最大的 >aij,右边最小的 >aik;或者左边最大的 <aij,右边最小的 <aik。显然 (j,i,k) 是一组合法方案。

n=4 当且仅当两个端点都不是最值,考虑枚举最右端的 x,考虑找到最优秀的最大和最小值,容易发现 p2,p3 只能分别在前缀最大 / 最小单调栈中取到。

p4 一定不在任何一个单调栈内,否则它会成为最值。

在两个单调栈上二分出第一个 >ax<ax 的位置,设为 y,z,找到 max(y,z) 之后的第一个 “空隙”,即不在任何一个单调栈中的元素,这一定是最靠左的 p4p3 就取 p4 之前的第一个元素,p2 同理。

找出这些 (p1,p4) 后离线二维数点即可。找 p2,p3,p4 的过程可以在单调栈上二分和线段树上二分。时间复杂度 O(nlogn)

本文作者:henrici3106

本文链接:https://www.cnblogs.com/henrici3106/p/17259644.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   henrici3106  阅读(69)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.