一次函数最优化数据结构
哎呀没写完,明天再补吧
李超线段树
一个节点维护递归到这个点,包含整个区间,并且在mid处取值最大的线段。
若有两条线段,其中x比y在mid处值更大,如果x在l和r处值都比y大,显然y没有用。否则y只可能在左区间或右区间比x优。
李超线段树利用单侧递归保证时间复杂度。
但是李超线段树不便于删除线段,可以使用时间维度上的线段树分治
CF932F Escape Through Leaf
首先有一个显然的dp,\(dp[x]=min(a_x\times b_y+dp[y])\)其中y在x的子树内。
那么令\(a_x\)为\(x\),\(b_y\)为\(k\),\(dp[y]\)为\(b\),那么这就变成了一些一次函数在\(a_x\)处的函数值,可以使用李超线段树合并。
凸包
凸包在一次函数最优化中有很重要的应用。
P3195 [HNOI2008] 玩具装箱
斜率优化板题,但是本来斜率优化就可以用凸包来理解,所以为什么不直接写凸包。
考虑长度计算时有一个\(j-i\),所以先把所有\(C_i\)都加上一个\(1\),\(sum_i\)表示前缀和
考虑先写出普速的\(dp\)式子:
\(dp[i]\)=min{\(dp[j]+(sum[i]-sum[j]-L)^2\)}
推式子,
\((sum[i]-sum[j]-L)^2\)
\(=((sum[i]-L)-sum[j])^2\)
\(=(sum[i]-L)^2+sum[j]^2-2(sum[i]-L)sum[j]\)
其中\((sum[i]-L)^2\)可以预处理,
P3309 [SDOI2014] 向量集
观察两个向量\((a,b)\)和\((x,y)\)的点积\(ax+by\)
可以把\(b\)给提出来,变成\(b(\frac{a}{b}x+y)\)
考虑令斜率\(k=\frac{a}{b}\),那么括号里就变成了一个一次函数的形式,相当于每一次给定\(k\)计算最大或最小截距(因为b可正可负)。
可以手模一下发现任何在凸包内的点要么不如它左侧的凸包上的点优,要么不如右边的优。
因此我们直接把每一个向量\((x,y)\)当成一个点\((x,y)\)求凸包。
可是题目询问的是区间点积最大值,也就是说我们要用线段树来维护区间内的凸包。
这就带来了一个问题,如果我们每次加一个向量都把所有包含它的区间都暴力重构凸包,肯定是不行的。
(听说有单log维护凸包的科技但我不会)
所以考虑利用线段树的优势,如果每个没有处理好答案区间的左区间都处理好了答案,那么其实我们只会单侧递归右区间,时间复杂度是有保证的。
又因为没有删除操作,所以一个区间一旦被完全覆盖凸包自然不会变。
所以我们选择插入一个向量后只更新以它的位置为结尾的区间的凸包。
这样是单log的。
UOJ191. 【集训队互测2016】Unknown
把前一个题的点乘换成了叉乘,换汤不换药。
这道题没有强制在线,不知道离线能做到什么时间复杂度。
但是这个题要支持删除,就不能像上一个题一样更新了,这个时候有一个神奇的想法。
我们肯定还是要利用线段树的优势,我们发现,如果一个区间后面的那个和它等长的区间已经被填完了,那么想要删到前面的区间就至少先把后面的删完。
肯定区间等长更好,但是线段树的区间不一定等长,如果前面的区间很长,然后后面的区间正好结束所以很短,时间复杂度就会出问题。
这个时候我们就需要二进制分组(zkw线段树),强行把每个区间的长度填成2的次方
这样时间复杂度就对了。
LOJ6265. 最大连续子段和
首先有个槽点,这道题在LOJ上可以直接暴力过
P8987 [北大集训 2021] 简单数据结构
这几天听了几遍。
首先发现很特别的一点,操作1和操作2都是全局操作,先记下来。
序列a有初值,这不好搞,先从a没有初值开始考虑。
若a没有初值,那么因为操作为全局操作,所以每一次直接线段树二分加上后缀checkmin,打一个标记就好。
但是a有初值,不难发现可以把数分成两个部分,一部分S已经被checkmin,另一部分T还没有。
S是好维护的,关键是把T中的元素转移到S中。
考虑维护凸包,记录操作1的次数c,每一次操作2的时候相当于用一条斜率为-c的直线截这个凸包,所有在截线以上的点都要放到S中。
但是你考虑有一个问题,就是可能凸包里面的点也可以到S中,那么凸包需要一直更新,如果只维护一个凸包,暴力更新肯定会费。
但是我们不想使用科技,所以直接上一个分块,凸包太大不好更新,就把凸包变小一点。
考虑每次更新都会删掉一个点,所以维护凸包的复杂度为\(O(n\sqrt n)\)

浙公网安备 33010602011771号