wqs二分与闵可夫斯基和学习笔记

重新学了一下这方面的知识。

首先要理解wqs二分为啥只能做凸函数,以及理解二分的本质是在二分斜率。
可以看下面这篇介绍

https://www.luogu.com.cn/blog/daniu/wqs-er-fen

然后再就是wqs二分与闵科夫斯基和的关系。
可以参考这篇文章。

https://www.luogu.com.cn/blog/Flying2018/wqs-er-fen-min-ke-fu-si-ji-hu-xue-xi-bi-ji

通常来说维护闵科夫斯基和只需要维护差分数组即可。

整几个例题

这里需要注意的点就是原本的(dp)方程为$f_{l,r,k,0/1,0/1}=max(f_{l,i,j,0/1,0/1}+f_{i+1,r,k-j,0/1,0/1})

即需要枚举(i)进行转移

但是实际上可以不用,因为我们记录了区间的左右端点是否被选。我们可以对于任意一个分段点,考虑左右两边的段是否拼接在一起即可,因此转移我们可以任意选择一个(i)
所以考虑取中心,然后分治+闵可夫斯基和即可。

显然考虑线段树维护闵科夫斯基和。

然后对于每个询问,我们先考虑(wqs)二分,并把询问区间拆位(logn)段,然后再这(logn)段的闵可夫斯基和上分别二分查找对应的斜率,依次拼接起来即可。

这样的时间复杂度是O(nlog^3n),非常的慢。

实际上,不难发现线段树一共有个O(nlogn)个点,但我们刚才的做法却总共进行了(O(nlog^2n))次线段树上的闵科夫斯基和的二分,这显然非常不优秀。

我们可以考虑把询问按照(k)排序,然后线段树上每个节点一个指针,然后(k)动的时候动态搞一下就好。

???
这样的复杂度就变成了两个logn

https://codeforces.com/group/wmhDiB5PTN/contest/341884/problem/J
显然转化为树后考虑(dp)

暴力(dp)是$O(n^2)的
方程大概是这个样子

[f[x][i]=max(sum f[y][i],sum f[y][i-1]+ w[x]) ]

对于这种题,几乎有一个固定套路。
大概就是首先猜想(f)关于凸或凹,然后不难发现令(f[x][i]=sum f[y][i])
只需要算一下这个凸包和向量((1,w[x]))的闵科夫斯基和即可。
所以我们考虑维护每个点的闵科夫斯基和对应的差分数组。
然后转移的话先暴力把所有儿子加起来,然后二分插入一个向量((1,w[x]))
这样做的话复杂度依然是不对的。
有一个很简单的优化,直接进行轻重链剖分,由于是加和,我们可以直接让父亲继承中儿子的数组,然后对于轻儿子暴力对应点值相加即可。
综上时间复杂度(O(nlogn——nlog^2n))

原文地址:https://www.cnblogs.com/Creed-qwq/p/15415868.html