jzoj5241【GDOI2018模拟8.8】苹果和雪梨 贪心

73 篇文章 0 订阅
27 篇文章 0 订阅

Description

作为新开的水果连锁店店员,你需要把总部发给你的苹果和雪梨分组出售,从而获得最
大利润。
总部发给你的水果包括:
n 个苹果,质量分别为a1,a2…an
n 个雪梨,质量分别为b1,b2…bn。
你卖的是盒装水果,一盒水果包括一个苹果和一个雪梨,苹果的质量乘上雪梨的质量就
是这盒水果的价钱。把苹果雪梨配对分成总共n 盒水果后,你要把价格最高的一盒返还给
水果店总部,剩下n-1 盒水果价格的和就是你的利润。注意:虽然返还给水果店总部的水
果不算在你的利润里,但是你必须把价格最高的一盒水果返还给总部。

Input

第一行一个正整数n。
第二行n 个正整数表示苹果的质量a1,a2…an。
第三行n 个正整数表示雪梨的质量b1,b2…bn。

Output

一个正整数,表示除了价格最大的那盒水果外其他水果的价格和的最大值(你的利润)。

Sample Input

输入1:
3
2 3 4
2 3 4

输入2:
3
2 3 100
2 3 100

Sample Output

输出1:
16

输出2:
304

Data Constraint

对于10%的数据n<=5
对于30%的数据n<=50
对于50%的数据n<=100
对于100%的数据n<=3000, ai<=1e7 bi<=1e7

正解有点恶心。
枚举最大值,首先保证已经做过的最大值方案最优(匹配),然后对于当前最大值V,假设他的匹配为x,y那么我们可以发现:
对于x原来的匹配pos[x]和y原来的匹配`,a[x]*b[y]+a[bl[y]]*b[pos[x]]>=a[x]*b[pos[x]]+a[bl[y]]*b[pos[x]],最大值相同,所以直接消去。
那么说明每一次我们都需要对当前的匹配进行交叉互换,可以保证是最优的,否则就不能交叉互换,只有当前匹配不满足时才可以交换,否则就不是最优的。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
typedef long long ll;
struct node
{
    int x,y;
    ll v;
}c[9000005];
int a[N],b[N],pos[N],bl[N],n;
inline bool cmp(node a,node b)
{
    if (a.v!=b.v)return a.v<b.v;
    if (a.x!=b.x)return a.x<b.x;
    return a.y<b.y;
}
int main()
{
    freopen("fruits.in","r",stdin);
    freopen("fruits.out","w",stdout);
    scanf("%d\n",&n);
    fo(i,1,n)scanf("%d",&a[i]);
    fo(i,1,n)scanf("%d",&b[i]);
    sort(a+1,a+1+n),sort(b+1,b+1+n);
    int tot=0;
    fo(i,1,n)
    {
        fo(j,1,n)
        {
            c[++tot].v=1ll*a[i]*b[j];
            c[tot].x=i,c[tot].y=j;
        }
    }
    sort(c+1,c+1+tot,cmp);
    ll ans=0,sum=0;
    fo(i,1,tot)
    {
        int x=c[i].x,y=c[i].y,k=bl[y];
        if (k==0)
        {
            sum-=1ll*a[x]*b[pos[x]]-1ll*a[x]*b[y];
            bl[pos[x]]=0;pos[x]=y;bl[y]=x;
        }
        else
        {
            sum-=1ll*a[x]*b[pos[x]]+1ll*a[k]*b[y];
            swap(bl[y],bl[pos[x]]);
            swap(pos[x],pos[k]);
            sum+=1ll*a[x]*b[pos[x]]+1ll*a[k]*b[pos[k]];
            bl[y]=x;
        }
        ans=max(ans,sum-c[i].v);
        //printf("%lld\n",sum);
    }
    printf("%lld\n",ans);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值