斜率优化

news/2024/9/20 0:32:16/文章来源:https://www.cnblogs.com/Atserckcn/p/18326284

斜率优化

[HNOI2008] 玩具装箱

状态转移方程:
$$
f_i=min(f_i,f_j+(sum_i+i-sum_j-j-L)^2){i>j}
$$
设A为 $sum_i+i$,B为 $sum_j+j+L+1$

简化可得:
$$
f_i=min(f_i,f_j+A2-2AB+B2)
$$
稍微分解一下,有:
$$
f_i=f_j+A2-2AB+B2
\
f_j+B2=2AB+f_i-A2
$$
设 $f_j+B^2$ 为点 $y$,$2A$ 为 $k$,$B$ 为 $x$,$f_i-A^2$ 为 $b$。

考虑一个确定的点 $(B,f_j+B^2)$,$k=2A$​ 的最小截距。

对于每个确定的 $i$,可令斜率为 $h_i$ 的直线过每个决策点,都可求得一个截距。根据状态转移方程可知,其中截距最小的直线方程所经过的决策点即为左右决策。

斜率:

先看一张图:

  • 斜率(↑↑↑)

斜率就是坡度,是高度的平均变化率,用坡度来刻划道路的倾斜程度,也就是用坡面的切直高度和水平长度的比,相当于在水平方向移动一千米,在切直方向上升或下降的数值,这个比值实际上就表示了坡度的大小。

即:设 $(0,0)$ 点为 $a$,$(3,0)$ 点为 $b$,则点 $B$ 的斜率为 $\frac{|b-a|}{B-b}$​。

以下称 $x_j$ 为 $x$ 轴的 $j$ 点,$y_i$ 为在 $y$ 轴的 $i$ 点。

在绝v额集合中筛选出部分决策,使得在 $x_j$ 递增的顺序下,相邻的决策点所炼成的线段的斜率单调递增。对于任意连续的三个所选决策 $j_{i-1},j_{i},j_{i+1}$,都有:
$$
\frac{f_{j_{i}}-f_{j_{i-1}}}{x_{j_i}-x_{j_{i-1}}}<\frac{f_{j_{i+1}}-f_{j_{i}}}{f_{j_{i+1}}-f_{j_i}}
$$
在对应坐标系中,相邻点之间连成的线段呈现出“下凸”形态,即为“凸包”。

  • 凸包(↑↑↑)

若斜率函数 $h_i$ 与 $x_j$ 均为单调递增函数,随着 $j$ 的递增,决策点的横坐标也单调递增,新决策必定会出现在整个凸包的最右端。又因为斜率函数具有单调性,所以每次需要求解的直线斜率 $h_i$ 也单调递增。决策集合仅保留下凸曲线上相邻现代斜率大于 $h_i$ 的剩余决策点,所以曲线最右端的决策点即为最优决策。

  • 最优决策、最优斜率、截距(设B点为最佳决策点)

根据如上性质,我们不难想出,用双端队列 q[l~r] 维护下凸曲线,队列中保存部分决策,对应下凸曲线上的决策点,满足 $x_i$​ 和 $h_i$​​ 都递增。

具体实施方案:

  • 为了保证队头即为最优决策,仅需保留下凸曲线上斜率大于 $h_i$ 的点,从队头开始检查决策 $q_l$ 和后续决策 $q_{l+1}$ 对应点连接线的斜率。若该斜率小等于 $h_i$,则把 $q_l$ 出队,继续检查寻得队头和后续决策,直至线段斜率大于 $h_i$。
  • 直接取队头决策 $j=q_l$ 为最优决策,进行状态转移。
  • 将当前状态 $i$ 为新的决策从队尾插入。在插入前需要维护凸曲线性质,即三个决策点 $q_{r-1},q_r,i$ 对应的相邻线段需要满足斜率单调递增,否则吧决策 $q_r$ 出队,继续检查 $q_{r-2},q_{r-1},i$,直至满足要求。设此操作一共进行了 $n$ 轮,则最终需要判断的三个状态为 $q_{r-n},q_{r-n+1},i$。

时间复杂度:$O(N)$。

  • 若斜率函数 $h_i$ 不满足单调性,则 $x_j$ 为单调递增函数,队头不为最优决策,须保留整个下凸曲线,可在队列中二分查找,求出一个位置 $k$,使得:

$$
\forall\ p\ <\ k
\
\forall\ q\ >\ k
\
h_p<h_k<h_q
$$

若满足以上条件,则 $k$ 为最优决策。

时间复杂度:$O(n \log n)$。

AC Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,l;
const ll MAXN=5e4+5;
ll q[MAXN],sum[MAXN],f[MAXN];
ll head=1,tail=1;
ll j;
inline ll x(ll j)//x坐标 
{return sum[j];
}
inline ll y(ll j)//y坐标 
{return f[j]+(sum[j]+l)*(sum[j]+l);
}
inline double slope(ll i,ll j)//计算 
{return (double)(y(j)-y(i))/(x(j)-x(i));
}
inline ll compute(ll i,ll j)//代价公式 
{return (sum[i]-sum[j]-l)*(sum[i]-sum[j]-l);
}
int main(){scanf("%lld%lld",&n,&l);l++;//因为一直都是-l-1,干脆直接变为 -(l+1) for(ll i=1;i<=n;i++){scanf("%lld",&sum[i]);sum[i]+=sum[i-1]+1;//前缀和 }q[tail]=0;for(ll i=1;i<=n;i++)//dp{while(head<tail&&slope(q[head],q[head+1])<=(sum[i]<<1))//出队首条件 head++;j=q[head];//队首 f[i]=f[j]+compute(i,j);//计算 while(head<tail&&slope(q[tail-1],q[tail])>=slope(q[tail-1],i))//出队末条件 tail--;q[++tail]=i;//最优决策入队 }printf("%lld\n",f[n]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/772188.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

矩阵的奇异值分解(SVD)及其应用

该博客针对矩阵的奇异值分解(SVD)展开介绍,主要介绍了奇异值分解的计算及其几何意义,并基于C++编程语言举例说明了SVD分解的一些应用。奇异值分解(Singular Value Decomposition, SVD)是矩阵的一种分解方法,与特征值分解不同,它可以应用于长方矩阵中,并将其分解成三个…

浮点数

FP32: 1bit符号位,10bit指数,23bit底数位。FP16: 1bit符号位,5bit指数,10bit底数位。FP16转FP32NAN/INF:对应的FP32的值 +0/-0: +0/-0 normal:指数+0x70,底数左移13位 subnormal:对应的FP32属于normal,需要继续左移至最高位为1的省略掉。(0x0078, 需要左移四位),指…

主动触发异常和自定义异常

主动触发异常自定义异常点击查看代码try:raise MyError("raise MyError,e就是里面的")except MyError as e:e.log()print(e)print(e.args) # 就是raise MyErrorprint(e.__class__.__name__) # 就是MyErrorprint(e.__class__)except Exception as e:traceback.prin…

python-数据交换

a=10 b=20 a, b = b, a #数据交换 print(a, b)#a, b, c, d = d, c, b, a

性能测试工具 - Siege

在快速发展的技术时代,网站和应用的性能对于用户体验和业务成功至关重要。作为测试工程师,找到高效的性能测试工具显得尤为重要。今天,我们来聊聊一个备受推崇的性能测试工具——Siege。为什么Siege能够在众多性能测试工具中脱颖而出?它究竟有哪些独特之处,能帮助测试人员…

2024暑假集训测试12

前言比赛链接。T2 其实和货车运输这题差不多但是由于给定图为树的部分分都没想出来压根没想到重构树,感觉不太应该,思路还是不清晰,赛时没有拿到那个部分分的,因为拿到的都顺着推出正解了;T3 是道黑,赛时 \(A,B\) 循环输出能拿到 \(40\) 分,赛后重测了;T4 题都看不懂。…

中大企业如何选择高效的缺陷管理系统?

国内外主流的10款中大型企业使用的缺陷管理系统对比:PingCode、Worktile、禅道云、Testin、FineReport、华为DevCloud、Jira、Bugzilla、Redmine、Trac。在选择适合中大型企业的缺陷管理系统时,关键的挑战在于找到一个既能满足独特业务需求,又能提供可扩展性和高效率的解决方…

暑假集训CSP提高模拟8

T2 赛时想法是维护\(m\)个并查集,二分答案,然后比较祖先是否相同,\(O(mlogn+qmlogn)\)的复杂度,而且内存开不下,只拿\(20pts\)点击查看代码 #include <bits/stdc++.h> #define ll long long #define pb push_back using namespace std; const int N = 1e5+5; vector <…

java位运算

位运算符:针对二进制的值补码形式进行计算的 & | ^(相同为0,不同为1) ~ << >> >>>public class WeiOptDemo1 { public static void main(String[] args) { byte a1 = 3; byte b1 = 4;System.out.println(a1 & b1);System.out.println(a1 | b1)…

【Azure APIM】调用APIM的备份接口时候遇见InvalidParameters错误

问题描述 根据官方文档,可以调用REST API来对APIM执行备份操作。要备份 API 管理服务,请发出以下 HTTP 请求: POST https://management.chinacloudapi.cn/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ApiManagement/service/{s…

kruskal重构树

比较好理解,相当于重建了一个二叉树,所有的父亲节点都为原来图中的边,儿子节点为点。 重构树就可以利用lca求两点间的最大(或者最小)边权以及一些树上操作。较为简单的应用,需要用线段树来维护信息。点击查看代码 #include<bits/stdc++.h> using namespace std;con…