1、单调栈:因为是循环数组,因此把数组复制三遍,ans 数组复制为2倍长,维护一个单调非递增的栈,栈保存的元素是元组(a[i] , i ),如果后面的值有比栈顶元素的值大,栈顶元素出栈,更新ans[i]的值为让其出栈的值,最后返回ans数组的一半,即最终答案。 2、线段树:数组复制两遍,构建线段树,存的值是当前区间的最...
在经过一晚上和某考试题的奋斗后,我终于确定了那道题不能用线段树维护单调栈做,同时对这个算法有了更深的理解。 前言: 众所周知,线段树啥都能干。 求出最长上升/下降子序列,肯定可以O(n)O(n)单调栈跑一遍。但是如果套上单点修改和多次询问,O(n2)O(n2)的复杂度可能就吃不消了,所以,用线段树来求出这个最...
设维护最大值的单调栈中相邻两个位置是 x,y。 比如我们枚举到了这个位置 此时栈为 [7,5] (这里的数是 a[i] ,而 x,y 说的是数的下标)。此时栈中相邻的两个数的位置。 那么我们有,若 y 为奇数 / 偶数,则区间 [x+1,y] 中的下标为奇数 / 偶数的所有位置 j 满足区间 [j,i] 中的最大值在奇...
维护单调栈,栈中两个元素之间的左端点对应的 \max 是相同的,贡献可以看做区间加。 而单调栈的变化次数时均摊 O(n) 的,则会产生 O(n) 个区间加法。 将右端点移动到 r 时维护左端点的线段树状态称为版本 r。 设v(l,r) 为区间 [l,r] 的价值。 若我们需要求出 \sum\limits_{i=l}^rv(i,r) ,则...
L. Continuous Intervals(单调栈 + 线段树 + 思维) 给定一个长度为 n n n的数组,问里面有多少个区间 [ l , r ] [l, r] [l,r],满足,对这个区间排序后,两两差值$ \leq 1$,输出区间个数。 如果说区间 [ l , r ] [l, r] [l,r]是符合要求的,则满足 m a x ( a l , … , a r )...
因为是循环数组因此把数组复制三遍ans数组复制为2倍长维护一个单调非递增的栈栈保存的元素是元组aii如果后面的值有比栈顶元素的值大栈顶元素出栈更新ansi的值为让其出栈的值最后返回ans数组的一半即最终答案 LeetCode503:下一个更大的元素(单调栈or线段树)...
(r-l+1)\ge 0\),因此我们可以开一棵线段树,线段树上 \(l\) 位置上的值就是 \(\max\limits_{i=l}^ra_i-(r-l+1)\),显然该线段树可以单调栈维护,那么我们只需要求出 \([l',p]\) 最小值即最小值个数即可算出贡献,具体来说如果最小值不为 \(0\) 那么贡献为 \(0\),否则贡献就是最小值...
线段树在维护区间时可以维护⼀个单调栈。题意:维护全局最⼤上升序列⼤⼩。更新 线段树当前节点存储整个区间的最⼤值,对于该题,左⼦树的区间答案可以直接继承,然后⽤左⼦树区间的最⼤值查询右⼦树的答案并记录在该节点上。void update(const int &x,const double &k,const int &ro=1,const ...
RMQ (Range Minimum/Maximum Query) 问题是指:对于长度为 n 的数列 A,回答若干询问 RMQ (A, i, j) 其中 i, j <= n,返回数列 A 中下标在 i, j 里的最小 (大)值。也就是说:RMQ 问题是指求区间最值的问题。通常该类型题目的解法有递归分治、动态规划、线段树和单调栈 / 单调队列。
区间更新显然⽤线段树解决,线段树叶⼦结点维护第i个位置被加次数,即以第i个结点为起点的LIS长度 本题是枚举长为k的区间,求每个区间的LIS,那么只要在更新时查询区间[i-k+1,i]的最⼤值即可 要先预处理出第⼀个⽐a[i]⼤的a[i]左边的数的下标 : 单调栈 */ #include<bits/stdc++.h> #...