首先
i
i
越大越大
所以dp,
fi,j
f
i
,
j
表示
ai
a
i
和
bj
b
j
配的最大获利
所以有
fi,j=max{ft,k−(sbj−1−sbk)2−(sai−1−sat)2}
f
i
,
j
=
m
a
x
{
f
t
,
k
−
(
s
b
j
−
1
−
s
b
k
)
2
−
(
s
a
i
−
1
−
s
a
t
)
2
}
,其中
sa,sb
s
a
,
s
b
两数组的前缀和
又可以发现最优的转移满足
t=i−1,k=j−1
t
=
i
−
1
,
k
=
j
−
1
这两个其中之一,因为如果不满足,可以选
ai−1
a
i
−
1
和
bj−1
b
j
−
1
配对,答案更优
所以dp方程式可以表示为
fi,j=max{fi−1,t−(sbj−1−sbt)2,fk,j−1−(sai−1−sak)2}
f
i
,
j
=
m
a
x
{
f
i
−
1
,
t
−
(
s
b
j
−
1
−
s
b
t
)
2
,
f
k
,
j
−
1
−
(
s
a
i
−
1
−
s
a
k
)
2
}
现在两种转移分开考虑,化简,得到
t
t
比优的情况,满足
其中①中的 gt=fi−1,t−sb2t g t = f i − 1 , t − s b t 2 ,②中的 gt=ft,j−1−sa2t g t = f t , j − 1 − s a t 2
维护两个上凸壳,搞一个二维的斜率优化就可以了
代码略(特别)丑
代码如下:
#include<algorithm>
#include<ctype.h>
#include<cstdio>
#define INF 21474836470000ll
#define N 1050
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
typedef long long LL;
int n,l,r;
int a[N],b[N],ly[N],ry[N];
LL ans;
LL sa[N],sb[N],f[N][N];
struct Point{
LL x,y;
Point(){}
Point(LL _,LL __):x(_),y(__){}
}qi[N],qj[N][N],tmp;
inline double Slope(Point a,Point b){
if(a.x==b.x) return a.y>b.y?-INF:INF;
return 1.0*(b.y-a.y)/(b.x-a.x);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
sa[i]=sa[i-1]+a[i];
}
for(int i=1;i<=n;i++){
b[i]=read();
sb[i]=sb[i-1]+b[i];
}
for(int i=1;i<=n;i++)
ly[i]=1;
for(int i=1;i<=n;i++){
l=1;r=0;
for(int j=1;j<=n;j++){
f[i][j]=a[i]*b[j]-sa[i-1]*sa[i-1]-sb[j-1]*sb[j-1];
while(l<r && Slope(qi[l],qi[l+1])>-sb[j-1]*2)
l++;
if(i>0 && l<=r)
f[i][j]=max(f[i][j],qi[l].y+sb[j-1]*2*qi[l].x-sb[j-1]*sb[j-1]+1ll*a[i]*b[j]);
/上面是从i-1转移
while(ly[j]<ry[j] && Slope(qj[j][ly[j]],qj[j][ly[j]+1])>-sa[i-1]*2)
ly[j]++;
if(j>0 && ly[j]<=ry[j])
f[i][j]=max(f[i][j],qj[j][ly[j]].y+sa[i-1]*2*qj[j][ly[j]].x-sa[i-1]*sa[i-1]+1ll*a[i]*b[j]);
/从j-1转移
if(i-1){
tmp=Point(sb[j],f[i-1][j]-sb[j]*sb[j]);
while(l<r && Slope(qi[r],tmp)>Slope(qi[r-1],qi[r]))
r--;
if(i-1) qi[++r]=tmp;
}
///上下全是更新队列
if(j-1){
tmp=Point(sa[i],f[i][j-1]-sa[i]*sa[i]);
while(ly[j]<ry[j] && Slope(qj[j][ry[j]],tmp)>Slope(qj[j][ry[j]-1],qj[j][ry[j]]))
ry[j]--;
qj[j][++ry[j]]=tmp;
}
}
}
for(int i=1;i<=n;i++)
ans=max(ans,max(f[i][n]-(sa[n]-sa[i])*(sa[n]-sa[i]),f[n][i]-(sb[n]-sb[i])*(sb[n]-sb[i])));
printf("%lld",ans);
return 0;
}