BZOJ_1713_[Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会_斜率优化
BZOJ_1713_[Usaco2007 China]The Bovine Accordion and Banjo Orchestra 音乐会_斜率优化
Description
Input
第1行输入N,之后N行输入Ai,之后N行输入Bi.
Output
输出最大收益.
Sample Input
3
1
1
5
5
1
1
INPUT DETAILS:
There are 6 cows: 3 accordionists and 3 banjoists. The accordionists have
talent levels (1, 1, 5), and the banjoists have talent levels (5, 1, 1).
1
1
5
5
1
1
INPUT DETAILS:
There are 6 cows: 3 accordionists and 3 banjoists. The accordionists have
talent levels (1, 1, 5), and the banjoists have talent levels (5, 1, 1).
Sample Output
17
HINT
手风琴手3和班卓琴手1搭配,创造收益25美元.手风琴手1和手风琴手2喝酒用了4美元.同样班卓琴手2和班卓琴手3用了4美元.最后收益为25 -4-4=17美元
设F[i][j]表示手风琴手匹配到第i个,班卓琴手匹配到第j个的最大收益。
F[i][j]=F[k][l]+A[i]*B[j]-(sa[i-1]-sa[k])^2-(sb[j-1]-sb[l])^2。
因为A[i]*B[j]一定是正的,所以选的越多越好。
转移只有两个是有用的,F[i][j]从F[i-1][k]和F[k][j-1]转移。
斜率优化即可。注意L和R都要用数组来保存,Q也要开成二维的。
两个队列分别存i和j。
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef double f2; typedef long long ll; #define N 1050 #define eps 1e-6 int a[N],b[N],n,l1[N],r1[N],l2[N],r2[N]; ll sa[N],sb[N],ans,f[N][N]; f2 gK(ll x,ll y,ll z,ll w) { if(z==x) return w>y?1e10:-1e10; return (1.0*w-y)/(z-x); } struct Point { ll x,y; int k; }Q1[N][N],Q2[N][N]; f2 Slp(const Point &a,const Point &b) { if(a.x==b.x) return b.y>a.y?1e10:-1e10; return 1.0*(b.y-a.y)/(b.x-a.x); } #define X1(k) (sb[k]) #define Y1(k,i) (f[i-1][k]-sb[k]*sb[k]) #define X2(k) (sa[k]) #define Y2(k,j) (f[k][j-1]-sa[k]*sa[k]) int main() { scanf("%d",&n); int i,j,k; for(i=1;i<=n;i++) scanf("%d",&a[i]),sa[i]=sa[i-1]+a[i]; for(i=1;i<=n;i++) scanf("%d",&b[i]),sb[i]=sb[i-1]+b[i]; ans=-1ll<<60; for(i=1;i<=n;i++) { for(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(l1[i]<r1[i]-1&&Slp(Q1[i][l1[i]],Q1[i][l1[i]+1])>-2*sb[j-1]) l1[i]++; k=Q1[i][l1[i]].k; if(l1[i]<r1[i]) f[i][j]=max(f[i][j],f[i-1][k]+a[i]*b[j]-(sb[j-1]-sb[k])*(sb[j-1]-sb[k])); // while(l2[j]<r2[j]-1&&Slp(Q2[j][l2[j]],Q2[j][l2[j]+1])>-2*sa[i-1]) l2[j]++; k=Q2[j][l2[j]].k; if(l2[j]<r2[j]) f[i][j]=max(f[i][j],f[k][j-1]+a[i]*b[j]-(sa[i-1]-sa[k])*(sa[i-1]-sa[k])); if(i>=2) { Point tmp=(Point){sb[j],f[i-1][j]-sb[j]*sb[j],j}; while(l1[i]<r1[i]-1&&Slp(Q1[i][r1[i]-1],tmp)>Slp(Q1[i][r1[i]-2],Q1[i][r1[i]-1])) r1[i]--; Q1[i][r1[i]++]=tmp; } if(j>=2) { Point tmp=(Point){sa[i],f[i][j-1]-sa[i]*sa[i],i}; while(l2[j]<r2[j]-1&&Slp(Q2[j][r2[j]-1],tmp)>Slp(Q2[j][r2[j]-2],Q2[j][r2[j]-1])) r2[j]--; Q2[j][r2[j]++]=tmp; } ans=max(ans,f[i][j]-(sa[n]-sa[i])*(sa[n]-sa[i])-(sb[n]-sb[j])*(sb[n]-sb[j])); } } printf("%lld\n",ans); }