CDQ 维护斜率优化DP
Building Bridges
code:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int MAXN=2e5+5;
int n,h[MAXN],w[MAXN],dp[MAXN],s[MAXN],q[MAXN];
int POW(int x){return x*x;
}
struct ren{
int id,x,y,k;
}a[MAXN],t[MAXN];
bool cmp(ren x,ren y){return x.k<y.k;
}
int X(int i){return h[i];
}
int K(int i){return 2*h[i];
}
int Y(int i){return dp[i]+POW(h[i])-s[i];
}
void cdq(int l,int r){
if(l==r){a[l].y=Y(l);return;
}
int mid=(l+r)>>1;
int t1=l,t2=mid+1;
for(int i=l;i<=r;i++){
if(a[i].id<=mid) t[t1++]=a[i];
else t[t2++]=a[i];
}
for(int i=l;i<=r;i++) a[i]=t[i];
cdq(l,mid);
int he=1,ti=0;
for(int i=l;i<=mid;i++){
if(i!=l&&a[i].x==a[i-1].x) continue;
while(he<ti&&(a[q[ti]].x-a[q[ti-1]].x)*(a[i].y-a[q[ti]].y)<=(a[i].x-a[q[ti]].x)*(a[q[ti]].y-a[q[ti-1]].y)) ti--;
q[++ti]=i;
}
for(int i=mid+1;i<=r;i++){
while(he<ti&&a[q[he+1]].y-a[q[he]].y<=a[i].k*(a[q[he+1]].x-a[q[he]].x)) he++;
dp[a[i].id]=min(dp[a[i].id],dp[a[q[he]].id]+POW(h[a[i].id]-h[a[q[he]].id])+(s[a[i].id-1]-s[a[q[he]].id]));
}
cdq(mid+1,r);
int i=l,j=mid+1,qq=l;
while(i<=mid&&j<=r){
if(a[i].x<a[j].x||(a[i].x==a[j].x&&a[i].y<a[j].y)) t[qq++]=a[i++];
else t[qq++]=a[j++];
}
while(i<=mid) t[qq++]=a[i++];
while(j<=r) t[qq++]=a[j++];
for(int i=l;i<=r;i++) a[i]=t[i];
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&h[i]),a[i].x=h[i],a[i].k=2*h[i],a[i].id=i,dp[i]=1e16;
dp[1]=0;
for(int i=1;i<=n;i++) scanf("%lld",&w[i]),s[i]=s[i-1]+w[i];
sort(a+1,a+1+n,cmp);
cdq(1,n);
printf("%lld",dp[n]);
return 0;
}
本文来自博客园,作者:{StranGePants},转载请注明原文链接:https://www.cnblogs.com/StranGePants/p/15889416.html