更应该说是一种思想吧。
我们希望知道恰好选择 个物品时的答案,但世界上哪来的那么多恰好呢。令 是恰好选择 个物品时的答案,那么点集 常会形成一个凸包,于是要知道特定 的答案,就只需要二分出这个点的斜率,然后用截距加上横坐标乘斜率即可,这个过程就是 wqs 二分,而求最优截距的方法是多样的,下面会说。其中有许多需要注意的细节,比如连着几个值斜率相同(其实没关系,反正最后求出来的答案是一样的)。另外精度也是一个需要考虑的问题。一般用下面这种写法:
while(l<r){
mid=(l+r>>1)+1;solve(mid);
if(g[1].num>=n)ans=g[1].data+n*mid,l=mid;else r=mid-1;
if(g[1].num==n)break;
}
最后出来的 就是我们想要的。其它的倒是没什么了,具体看题。
Akvizna link 忽略轮数的限制,用 代表还剩 个人的最大收益。于是有 ,可以拆成斜率优化的形式。推出柿子之后直接 wqs 二分即可,然后似乎要注意精度。
CF739E link 猜测答案在两个维度上都是凸包形式,所以可以二分套二分。检查的过程就变成了对于一个物品,用红球有 的贡献,用蓝球有 的贡献,两个都用有 的贡献,选择一个希望最大化总贡献,贪心即可,途中记录两种球各用几次。有些卡精度,应当在当前数量等于希望数量时及时推出。
aliens link 经典的题目。把右上的点翻到左下,消除那些对答案不产生影响的点,剩下的点会形成一个锯齿一样的形状,每个点映射到对角线上会有一个区间 。但由于多次选择的区间只会被计算一次,所以方程会稍微复杂一点(一开始以为要多次计算,调了半天才反应过来,毕竟那种思路下根本无法形成凸包)。内部还是用的斜率优化。
忘情 link 和上一道题本质上差不多。柿子题。
林克卡特树 link 转化问题。把树拆成 部分,然后要最大化连接起来后的答案,就贪心地选择每个部分中的直径。于是问题就变成了在树上选择 条不相交的链。因为所以这玩意是上凸的,所以采用 wqs 二分。用 代表这个点当前度数为多少时的最优值,考虑转移。用 代表 子树内的答案(也就是到父亲那条边不选),于是有
其中每个值都要记录两维,即答案和选择的链的数量。最后看 选择了几条链并更新左右端点即可。
CF802O link 运用到了 wqs 二分思想的题目。因为所以它是一个凸包,然后就可以用 wqs 二分了。考虑内部如何检查,这里用到了反悔 DP 的思想。考虑一个点作为结束时间时选择谁作为开始时间。如果选择一个没有被选择过的 ,那么由于当前是一个新的决策,所以贡献是 。如果是顶替掉之前的某个决策,那么贡献的变化值就是 ,所以动态维护 和 的最小值并记录第一种决策做了多少次即可。一只 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架