设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而递增,在有多解时强制取最大即可。