随笔分类 - 算法-数据结构
摘要:lcp 就是后缀树上的 lca。因为字符串随机,所以后缀树树高是 O(log n) 级别的。将询问离线,从小到大枚举 R,暴力跳祖先,更新一些 i 的答案。需要数据结构支持:前缀对一个值取 max,区间求和。发现要取 max 的值是 O(log n) 级别的,对每个值记录最大位置,就可以实现 O(1) 修改,O(log n) 查询。总时间复杂度 O(n log n)。
阅读全文
摘要:分 b > d 和 b <= d 两种情况讨论。关于 b, d 做 cdq 分治。每次考虑右边对左边的贡献,这样 b, d 的大小关系就解决了。第一种情况比较简单,就是在可持久化 01 trie 里查询一下就行了第二种可以考虑每个 b 对 d 的贡献,方法就和第一种情况差不多了,也就是把“查询”改成“打标记”。
阅读全文
摘要:本文提供了两种解法。一种是硬核数据结构做法。将限制转化为一个几何问题(双矩形的交),用扫描线求解。第二种是巧妙的贪心,证明了如何选择 n1, n2 是最有可能有解的,于是在确定 n1, n2 后,直接进行二分图染色即可
阅读全文
摘要:考虑查询一段区间 [l,r] 里线段并的长度怎么做。可以枚举右端点,维护左端点的答案。同时对数轴上每个位置,记录最后一个覆盖到它的线段编号,用 set 维护数轴上的这些线段。加入一条新线段时,要更新答案,相当于对一段左端点的答案做区间加。回到本题,可以二分价值第 k 大的区间的价值,然后求价值大于等于 mid 的区间数量,做法和上面类似
阅读全文
摘要:有关“序列、区间里、数值的出现次数”的问题,一般都要想到用莫队来维护。莫队后,往往就是要维护一个序列,支持单点修改,然后回答各种各样的询问。因为外层套了莫队,所以需要 O(1) 的单点修改,而询问则可以较慢。一般的数据结构(如线段树、平衡树),修改和查询都是 O(log n) 的,往往难以胜任。此时有一些巧妙的解决方法。
阅读全文
摘要:考虑实现一个核心函数:求出某个后缀,花费不超过 c 时,字典序第 k 小的结果序列,的第一次操作。实现这个函数后,通过调用不超过 c 次该函数,可以求出答案。我们对后缀做一些预处理,就可以快速实现这个核心函数。预处理需要观察一些性质,然后用 deque 实现。
阅读全文
摘要:很神的数据结构题!!!先做前缀和等初步转化,可以变成关于两个序列、区间最大、最小值的问题。枚举 r,用单调栈维护出使其中一个序列合法所需要做的操作。对另一个序列,可以贪心地在区间端点处进行操作。找出最小的、合法的区间端点,可以在线段树上二分。但这个线段树维护的信息比较特殊,要用到类似于《楼房重建》这题里,log^2 线段树的技巧。
阅读全文
摘要:树形 DP。把第二维搬到线段树上,然后线段树合并。这是常见的套路(NOI2020 d1t2),但在本题里会 MLE。进一步优化,需要根据题目性质(有效 DP 值的单调性),将线段树改为 set,做启发式合并。
阅读全文
摘要:做 KMP 后,从 fail[x] 向 x 连边,得到一个有根树森林。用树链剖分优化暴力跳 border 的过程,转化为一个序列上的数据结构问题。可以离线,进一步转化为静态的区间覆盖和区间最小值查询问题。
阅读全文
摘要:发现可能出现的 42 的幂很少。如果只有操作 3,我们可以暴力 while,用线段树修改,每个位置只会被更新 log_{42}(maxValue) 次,总时间复杂度 O((n + q) * log_{42}(maxValue) * log_{2}(n))。在有操作 2 时,每个位置上数值不再单调增加,会影响前面的复杂度分析。此时引入一种懒惰状态,表示数值等于它后面第一个非懒惰状态的值。在操作 2 时,只修改 r 位置,并把 [l, r - 1] 置为懒惰状态。因为每次只需要增加 O(1) 个非懒惰状态,时间复杂度正确。
阅读全文
摘要:题目来源:Codeforces,#678,Codeforces Round #678 (Div. 2),CF1436;CF1436E Complicated Computations,CF1436F Sum Over Subsets。 CF1436E Complicated Computations
阅读全文
摘要:不会删边,考虑倒序操作,删边变加边。但操作 1 又只能正序进行。所以考虑倒序加边建出重构树,然后正序处理操作 1。用线段树维护重构树的 dfs 序即可。
阅读全文
摘要:可以证明,我们总能通过巧妙地安排删除顺序,使得所有“理论上能被删除的数”都被删掉。那么,对于前i个数里最多能删多少个,容易得到递推式 f(i) = f(i-1) + [i>=a(i) and f(i-1)>=i-a(i)]。区间询问。我们对每个i,预处理出使得它能被删掉时,前面最多ban掉多少个数。预处理可以二分+主席树求。询问可以直接在主席树上查询。
阅读全文
摘要:先做一个二维DP:dp[u][i]表示点u的祖先边中离它最近的,颜色为1的边,深度为i,此时节点u子树内的边的染色方案数。然后把第二维搬到线段树上,做线段树合并
阅读全文
摘要:如果只有一次询问,可以分治,每次考虑跨过中点的情况。预处理左半边后缀or和,右半边前缀or和,然后用two pointers求。发现前、后缀or和只会变化O(log a)次。用线段树维护,记录每个区间的答案,以及前、后缀or和(这O(log a)个段)。push_up和查询时,还用two pointers的方法合并左右区间。
阅读全文
摘要:每次把两个相邻、相等的字符删掉,判断一个串是否合法,就是看能不能删光。分治。只考虑要交换的两位置一个在[l,mid],一个在[mid+1,r]的情况。如果交换后合法,那么左、右两边分别操作后剩下的串应该是对称的。可以用哈希值来判断。枚举要交换的两个字符分别是什么。通过扫描+用栈维护,就可以求出左、右两边每个位置,在被修改后的哈希值。
阅读全文
摘要:发现,球会滚到大于号和小于号中间形成的“坑”里。用线段树维护区间信息:最前面的一个坑,最后面的一个坑,已经中间的坑里最大的大小。合并区间时大力分类讨论。为了支持反转,我们可以在一开始建线段树的时候,就处理好“反转前”和“反转后”两套信息。当需要把一个区间反转时,就把这两套信息交换一下即可。
阅读全文