zoukankan      html  css  js  c++  java
  • 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).

    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
    ",ans);
    }
    
  • 相关阅读:
    The Network Adapter could not establish the connection问题研究
    条件更新或插入
    如何解决Oracle临时表空间过大
    oracle的临时表空间写满磁盘空间解决改问题的步骤
    如何在oracle中缩小临时表空间?ORA-01652无法在表空间中扩展temp
    oracle mysql sql 根据一张表更新另一张表
    Don’t Repeat Yourself,Repeat Yourself
    mysql oracle sql获取树 父级 子级 及自己
    hutool BigExcelWriter 下的autoSizeColumnAll异常问题
    Java手写数组栈
  • 原文地址:https://www.cnblogs.com/suika/p/9237264.html
Copyright © 2011-2022 走看看