BZOJ[1713][Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会 二维斜率优化

首先\(i\)越大\(j\)越大
所以dp,\(f_{i,j}\)表示\(a_i\)\(b_j\)配的最大获利
所以有\(f_{i,j}=max\{f_{t,k}-(sb_{j-1}-sb_{k})^2-(sa_{i-1}-sa_{t})^2\}\),其中\(sa,sb\)两数组的前缀和
又可以发现最优的转移满足\(t=i-1,k=j-1\)这两个其中之一,因为如果不满足,可以选\(a_{i-1}\)\(b_{j-1}\)配对,答案更优
所以dp方程式可以表示为\(f_{i,j}=max\{f_{i-1,t}-(sb_{j-1}-sb_t)^2,f_{k,j-1}-(sa_{i-1}-sa_k)^2\}\)
现在两种转移分开考虑,化简,得到\(t\)\(k\)优的情况,满足

\[\frac{g_t-g_k}{sb_t-sb_k}>-2sb_{j-1}\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,① $$\]

\frac{g_t-g_k}{sa_t-sa_k}>-2sa_{i-1},,,,,,,,,,,,,,,,,,,,,,②

\[其中①中的$g_t=f_{i-1,t}-sb_t^2$,②中的$g_t=f_{t,j-1}-sa_t^2$ 维护两个上凸壳,搞一个二维的斜率优化就可以了 代码略(特别)丑 代码如下: ```cpp #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; } ```\]

posted @ 2018-03-30 09:16  Duan2baka  阅读(201)  评论(0编辑  收藏  举报