商店街派对

设f[i][j]表示选了i个点,只考虑右端点不大于j的区间的最大收益。

转移方程为f[i][j]=f[i-1][k-1]+val(k,j)

其中val(k,j)表示l<=k<=r<=j的区间的价值之和。

一种想法是使用可持久化线段树维护。在插入j的时候继承j-1的结果,可持久化线段树的每个下标i维护val(j,i)

在查询时直接单点查询即可。

但是实际上不需要支持访问每个j的值,所以使用普通线段树插入即可。

这个做法的i这一维根据带权二分可以被去掉。如果设r(i)表示选了i个的答案,打出差分表发现是凸的。

所以可以带权二分。转移方程变为f[j]=f[j]+val(k,j)-md

实际上,后面的val也可以不使用线段树维护。

其实题目要求我们维护一个数组a,支持一下操作:

1.在末尾插入一个数

2.后缀加

3.单点查询。

可以使用并查集维护。注意到如果一个点j<k且f[j]+a[j]<f[k]+a[k],则k位置永远不能成为最大值。

所以可以把j链接到k,在查询一个点的时候直接查询find(i)即可。

维护差分表a[i]-a[i-1],当a[i]-a[i-1]>0时进行合并即可。

实际上,维护完后差分表都<0,所以在取dp值时直接取a[0]即可。

另外关于此题在凸包上有可能会出现三点共线,在dp的时候可能切到的点不随着mid而递增,在有多解时强制取最大即可。

原文地址:https://www.cnblogs.com/cszmc2004/p/13043965.html