线段树练习1
1.OJ 30277 nand
2.BZOJ4311 向量
\((x_1,y_1) \cdot (x,y) = x_1x+y_1y\)
两种思路
1. 斜率优化
令 \(y = y_1,k = -\frac{x}{y},x = x_1,b = \frac{ans}{y}\)
那么将 \((x_1,y_1)\) 当做一个坐标系上的点,维护一个下凸包,面对 \((x,y)\) 的询问就找到使 \(y = -\frac{x}{y} + ans\) 与下凸包相切的 \(ans\) 值,此为答案,维护凸包,树套树,将时间作为下标,有一个向量从 \(s\) 时刻被加入集合 \(t\)
时刻被删除,那么在 \([s, t]\) 中加入一个点 \((x,y)\),这样就解决了动态维护凸包只能加点不能删点的问题了。
2. 线性规划
令 \(y = answer, k = x_1,x = \frac{x}{y},b = y_1\),那么相当于要维护分段函数 \(y = \max (x_i x + y_i)((x_i, y_i) \in \mathcal{S})\),答案为令 \(x = \frac{x}{y}\) 时函数值的 \(y\) 倍。
3.CF1149C Tree Generator™
首先,我们根本不在意树的样子,考虑如何计算确定了深度最小的点之后所能得到的经过它的最长的链的长度,在括号序列中相当于确定一个右括号,向左找到(右括号数量-左括号数量)的最大值+向右找到(左括号数量-右括号数量)的最大值。
令右括号为-1,左括号为1,类似于最大区间和,只不过向右扩展时要取负号。
4.CF631E Product Sum
考虑将 \(x\) 号位置的数字移动到 \(y\) (令 \(y \leq x\),对于 \(y \geq x\) 的情况同理可得)。
令 \(fall[x] = \sum_{i = x}^{n} a[x]\)
即求 \(fall[y] + a[x]y\) 的最大值,令 \(k = y, x = a[x], b = fall[y]\),直接上李超线段树就行了。
类似第二题,本题应该也有维护凸包的做法,不过大同小异,懒得写了
5.CF932F Escape Through Leaf
\(dp[x] = \min (a_xb_y + dp[y])(y \in S_x)\)
令 \(k = a_x, x = b_y, b = dp[y]\),又是李超线段树,不过这次需要 \(DSU\) ,保留大子树的李超线段树,把剩下子树的节点暴力插进去就行了。
当然也可以用更简单的李超树合并,和线段树合并一样,一个节点不共有就直接返回,共有就继续递归,时间复杂度证明方法类似,为 \(n log n\)。
6.HEOI2016/TJOI2016 排序
典中典,二分变0/1,然后区间赋值,不想多讲了。
7.NOI2022 众数
1. 类主席树做法
建值域线段树,操作 \(1,2\) 直接维护,操作三采用多个线段树同时二分,假设当前的线段树走到了 \(p1, p2, p3,...,pm\),判断 \(tot[lson[p1]] + tot[lson[p2]] + ... + tot[lson[pm]]\) 大于总元素个数的一半则 \(pi <- lson[pi]\),否则 \(pi <= rson[pi]\),容易证明有且仅有 \(p1\) 这个点的权值可能作为众数。
2. 这辈子都做不到第二次的做法
一样建值域线段树,操作四一样是线段树合并。将序列里的不同的数两两对消,容易证明有且仅有最后剩下的这一种数字可能作为众数。询问直接返回最后剩的数及剩的数量就行了,然后再通过值域线段树查是否大于一半。