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;
}
posted @ 2022-02-13 15:14  StranGePants  阅读(59)  评论(0编辑  收藏  举报