洛谷有题目翻译
解题思路
设 表示青蛙跳到第 个石头的最小花费。
根据题意,易得转移方程:
(其中 )
这样的时间复杂度是 的,会超时。
所以我们考虑斜率优化。
斜率优化
将上面的转移方程展开,得:
将 看作常数,将 看作未知数,移项得:
两边同时 ,得:
对比 ,你就会发现:
观察 和 ,由于 是递增的,所以无需二分或 CDQ 分治。
直接斜率优化即可。
代码
注意:由于青蛙是从第一个石头开始跳的,所以我们不用将 0 号点加入凸包中。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,c;
int h[200001];
int f[200001];
int q[200001];
int dx(int i,int j)
{
int x1=h[i];
int x2=h[j];
return x1-x2;
}
int dy(int i,int j)
{
int y1=f[i]+(h[i]*h[i]);
int y2=f[j]+(h[j]*h[j]);
return y1-y2;
}
main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>c;
for(int i=1;i<=n;i++)
{
cin>>h[i];
}
int head=1,tail=0;
for(int i=2;i<=n;i++)
{
while(head<tail&&dy(q[tail],q[tail-1])*dx(i-1,q[tail])>=dx(q[tail],q[tail-1])*dy(i-1,q[tail]))
tail--;
q[++tail]=i-1;
while(head<tail&&dy(q[head+1],q[head])<=2*h[i]*dx(q[head+1],q[head]))
head++;
int j=q[head];
f[i]=f[j]+(h[i]-h[j])*(h[i]-h[j])+c;
}
cout<<f[n];
return 0;
}