由于点和斜率都没有单调性,要套一个 cdq 分治。没有什么坑点。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
typedef long long ll;
const int MAXN = 1e5 + 19;
struct Node{
int id;
ll x, y, k;
ll w, h, w_;
}node[MAXN], tmp[MAXN];
inline ll sqr(const ll& a){
return a * a;
}
inline bool cmp(const Node& a, const Node& b){
return a.k < b.k;
}
int n;
ll dp[MAXN];
int Q[MAXN], head, tail;
void cdq(int l, int r){
if(l == r){
node[l].x = node[l].h;
node[l].y = dp[l] - node[l].w + sqr(node[l].h);
return;
}
int mid = (l + r) >> 1, p = l, q = mid + 1;
for(int i = l; i <= r; ++i)
if(node[i].id <= mid)
tmp[p++] = node[i];
else
tmp[q++] = node[i];
for(int i = l; i <= r; ++i)
node[i] = tmp[i];
cdq(l, mid);
head = 1, tail = 0;
for(int i = l; i <= mid; ++i){
while(
head < tail &&
(node[i].y - node[Q[tail]].y) * (node[Q[tail]].x - node[Q[tail - 1]].x) <=
(node[Q[tail]].y - node[Q[tail - 1]].y) * (node[i].x - node[Q[tail]].x)
)
--tail;
Q[++tail] = i;
}
for(int i = mid + 1; i <= r; ++i){
while(
head < tail &&
node[Q[head + 1]].y - node[Q[head]].y <=
node[i].k * (node[Q[head + 1]].x - node[Q[head]].x)
)
++head;
dp[node[i].id] = std::min(dp[node[i].id], dp[node[Q[head]].id] + sqr(node[i].h - node[Q[head]].h) + node[i].w_ - node[Q[head]].w);
}
cdq(mid + 1, r);
int cnt = l; p = l, q = mid + 1;
while(p <= mid && q <= r)
if(node[p].x <= node[q].x)
tmp[cnt++] = node[p++];
else
tmp[cnt++] = node[q++];
while(p <= mid)
tmp[cnt++] = node[p++];
while(q <= r)
tmp[cnt++] = node[q++];
for(int i = l; i <= r; ++i)
node[i] = tmp[i];
}
int main(){
std::scanf("%d", &n);
for(int i = 1; i <= n; ++i)
std::scanf("%lld", &node[i].h), node[i].id = i, node[i].k = node[i].h * 2;
for(int i = 1; i <= n; ++i)
std::scanf("%lld", &node[i].w), node[i].w += node[i - 1].w, node[i].w_ = node[i - 1].w;
std::sort(node + 1, node + 1 + n, cmp);
std::memset(dp, 0x3f, sizeof dp); dp[1] = 0;
cdq(1, n);
std::printf("%lld\n", dp[n]);
return 0;
}