Java教程

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

本文主要是介绍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)\)

这篇关于wqs二分与闵可夫斯基和学习笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!