斜率优化
斜率优化
2020.10.8,具有纪念意义的一天,我学会斜率优化了!!感谢学长!!!
附上学长超高质量非常好懂的斜率优化讲解。
X严格递增,K严格递增。
P3195 [HNOI2008]玩具装箱
#include<bits/stdc++.h>
using namespace std;
#define ld long double
#define ll long long
const int N=5e4+5;
ll n,L,S[N],dp[N],q[N];
inline ll Y(int i){return dp[i]+S[i]*S[i];}
inline ll X(int i){return S[i];}
inline ld K(int i,int j){return (ld)(Y(j)-Y(i))/(X(j)-X(i));}
int main()
{
scanf("%lld %lld",&n,&L);L++;
for(int i=1;i<=n;++i) scanf("%lld",&S[i]),S[i]+=S[i-1]+1;
int l=1,r=0;q[++r]=0;
for(int i=1;i<=n;++i)
{
ld k=2*(S[i]-L);
while(l<r&&K(q[l],q[l+1])<=k) l++;
dp[i]=dp[q[l]]+(S[i]-S[q[l]]-L)*(S[i]-S[q[l]]-L);
while(l<r&&K(q[r-1],q[r])>=K(q[r-1],i)) r--;
q[++r]=i;
}
printf("%lld",dp[n]);
}
P2365 任务安排
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
const int N=5e3+5;
int q[N];
ll n,S,t[N],f[N],dp[N];
//dp[i]=min{dp[j]+t[i]*(f[i]-f[j])+S*(f[n]-f[j])
//dp[i]-t[i]*f[i]-S*f[n]+t[i]*f[j]=dp[j]+S*f[j]
//b + k * x =y
//k,x严格递增
inline ll Y(int i){return dp[i]-S*f[i];}
inline ll X(int i){return f[i];}
inline ld K(int i,int j){return (ld)(Y(j)-Y(i))/(X(j)-X(i));}
int main()
{
scanf("%lld %lld",&n,&S);
for(int i=1;i<=n;++i) scanf("%lld %lld",&t[i],&f[i]),t[i]+=t[i-1],f[i]+=f[i-1];
int l=1,r=0;
q[++r]=0;
for(int i=1;i<=n;++i)
{
while(l<r&&K(q[l],q[l+1])<=t[i]) l++;
dp[i]=dp[q[l]]+t[i]*(f[i]-f[q[l]])+S*(f[n]-f[q[l]]);
while(l<r&&K(q[r-1],q[r])>=K(q[r-1],i)) r--;
q[++r]=i;
}
printf("%lld",dp[n]);
}
X非严格递增,K严格递增
P5017 摆渡车
#include<bits/stdc++.h>
using namespace std;
#define ld long double
const int N=4e6+105;
int n,m,ans,T;
int G[N],S[N];
int dp[N],q[N];
//i*G[j]+dp[i]-G[i]*i-S[i]=dp[j]+S[j]
//k* x + b = y
inline int Y(int i){return dp[i]+S[i];};
inline int X(int i){return G[i];}
inline ld K(int i,int j)
{
return X(i)==X(j)?(Y(j)>Y(i)?2e9:-2e9):(ld)(Y(j)-Y(i))/(ld)(X(j)-X(i));
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1,t;i<=n;++i) scanf("%d",&t),G[t]++,S[t]+=t,T=max(T,t);
for(int i=1;i<T+m;++i) G[i]+=G[i-1],S[i]+=S[i-1];
for(int i=0;i<m;++i) dp[i]=G[i]*i-S[i];
int l=1,r=0;
q[++r]=0;
for(int i=m;i<T+m;++i)
{
while(l<r&&K(q[l],q[l+1])<=i) l++;
dp[i]=dp[q[l]]+(G[i]-G[q[l]])*i-(S[i]-S[q[l]]);
while(l<r&&K(q[r-1],q[r])>=K(q[r-1],i-m+1)) r--;
q[++r]=i-m+1;
}
ans=2e9+5;
for(int i=T;i<T+m;++i) ans=min(ans,dp[i]);
printf("%d",ans);
}
X非严格递增,K变幻莫测
P5785 [SDOI2012]任务安排
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
const int N=3e5+5;
int q[N],l=1,r=0;
ll n,S,t[N],f[N],dp[N];
//dp[i]=min{dp[j]+t[i]*(f[i]-f[j])+S*(f[n]-f[j])
//dp[i]-t[i]*f[i]-S*f[n]+t[i]*f[j]=dp[j]+S*f[j]
//b + k * x =y
//k变幻莫测,x非严格递增
inline ll Y(int i){return dp[i]-S*f[i];}
inline ll X(int i){return f[i];}
inline ld K(int i,int j)
{return X(i)==X(j)?(Y(j)>=Y(i)?1e18:-1e18):((ld)(Y(j)-Y(i))/(X(j)-X(i)));}
int ask(int k)
{
if(l==r) return q[l];
int L=l,R=r;
while(L<R)
{
int mid=(L+R)>>1;
if(K(q[mid],q[mid+1])<k) L=mid+1;
/*---------非常重要-----------*/
else R=mid;
/*---------非常重要-----------*/
}
return q[L];
}
int main()
{
scanf("%lld %lld",&n,&S);
for(int i=1;i<=n;++i) scanf("%lld %lld",&t[i],&f[i]),t[i]+=t[i-1],f[i]+=f[i-1];
q[++r]=0;
for(int i=1,j;i<=n;++i)
{
j=ask(t[i]);
dp[i]=dp[j]+t[i]*(f[i]-f[j])+S*(f[n]-f[j]);
while(l<r&&K(q[r-1],q[r])>=K(q[r-1],i)) r--;
q[++r]=i;
}
printf("%lld",dp[n]);
}
X变幻莫测,K变幻莫测
球球你,背模板。
P4655 [CEOI2017]Building Bridges
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define X(i) a[i].x
#define Y(i) a[i].y
#define id(i) a[i].id
#define k(i) a[i].k
const int N=1e5+5,INF=1e18;
int n,dp[N],h[N],sum[N],q[N];
struct node
{
int id,x,y,k;
}a[N];
inline bool cmp(node a,node b)
{
return a.k<b.k;
}
inline long double K(int i,int j)
{
return X(i)==X(j)?(Y(j)>Y(i)?INF:-INF):(long double)(Y(i)-Y(j))/(X(i)-X(j));
}
/*
2*hi*hj+b=dp[j]+h[j]*h[j]-sum[j]
*/
inline bool cmp1(node a,node b){return a.id<b.id;}
inline bool cmp2(node a,node b){return a.x!=b.x?(a.x<b.x):(a.y<b.y);}
void cdq(int L,int R)
{
if(L==R)
{
int j=id(L);
Y(L)=dp[j]+h[j]*h[j]-sum[j];
return;
}
int mid=(L+R)>>1;
int p1=L,p2=mid+1;
sort(a+L,a+R+1,cmp1);
sort(a+L,a+mid+1,cmp);
sort(a+mid+1,a+R+1,cmp);
cdq(L,mid);
int l=1,r=0;
for(int i=L;i<=mid;++i)
{
while(l<r&&K(q[r-1],q[r])>=K(q[r-1],i)) r--;
q[++r]=i;
}
for(int i=mid+1;i<=R;++i)
{
while(l<r&&K(q[l],q[l+1])<=k(i)) l++;
if(l<=r)
{
int x=id(i),j=id(q[l]);
dp[x]=min(dp[x],dp[j]+sum[x-1]-sum[j]+(h[x]-h[j])*(h[x]-h[j]));
}
}
cdq(mid+1,R);
sort(a+L,a+R+1,cmp2);
}
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;++i) scanf("%lld",&h[i]);
for(int i=1;i<=n;++i) scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
for(int i=1;i<=n;++i) a[i].id=i,a[i].x=h[i],a[i].k=2*h[i];
sort(a+1,a+n+1,cmp);
memset(dp,0x3f,sizeof(dp));
dp[1]=0;
cdq(1,n);
printf("%lld",dp[n]);
}

浙公网安备 33010602011771号