题意简述
有 n 个人,k 轮比赛。每次如果淘汰了 x 个人,还剩下 m 个人,得分增加 xm 的奖金。。假设你能控制每次淘汰多少人,最大化得分。
思路
设 dp[i] 表示现在还剩下 i 个人的最优方案 (先不考虑轮数)。
那么 dp[i]=max(dp[j]+i−ji),其中 0≤j<i
显然能斜率优化。
觉得不显然的小伙伴们看一下:
点击
斜率优化式子:
若 j≥k 且 j 优于 k,那么
dp[j]+i−ji>dp[k]+i−ki
dp[j]−ji>dp[k]−ki
dp[j]−dp[k]>j−ki
由于 j≥k,所以 j−k>0,直接除
dp[j]−dp[k]j−k>1i
也就是 slope(k,j)>1i 时,k 就没用了。
而如果每一个时刻 k 没用了,后面 i 更大,1i 更小,k 更不可能有用。这个是弹队首的条件。
其次可以看出来,这个队列是斜率单调递减的。这个就是加入队尾的条件。
然后我们就发现一个问题:k 的限制怎么办?
上 wqs 二分: 对于每个转移过来的 j,我们给他加上一个附加权值 x。显然,x 加的越多,选的段数越少。转移的时候记录一下段数,二分即可。
最后的答案是 ans−x×k,一定要记住了,是 k。
代码
点击
1 | #include <bits/stdc++.h> |