UVALive 6694 - Toy Boxes(枚举+三分)

题意:

给你n件物品,每件物品都有重量Wi,分在三个箱子里,每个箱子至少一件物品。求总费用最少(每个箱子费用=箱子总重量*箱子内物品总数)。

思路:

先按升序排序,若把物品分成总量连续的两份,以对称轴位置为x轴,费用为y轴,画出图形是一个单峰函数。高效率求单峰函数最值可以想到三分,但题目要求分成三份,所以要有两个对称轴,这时可以枚举第一个对称轴,求第二个对称轴。时间复杂度O(nlogn)。这题区间是int型的,所以可以通过mid,mid+1,求斜率来三分,效率更快。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll INFF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e4+7;
ll arr[maxn],sum[maxn];
int n;

ll getSum(int l,int r)
{
    return (ll)((sum[r]-sum[l])*(r-l));
}

ll trisearch(int x)
{
    int l = x+1,r = n;
    while(l<r-1)
    {
        int mid = (l+r)>>1;
        int midd  = mid+1;
        ll td = getSum(x,mid)+getSum(mid,n);
        ll tdd = getSum(x,midd)+getSum(midd,n);
        if(td<tdd)
            r = mid;
        else
            l = midd;
    }
    return min(getSum(x,l)+getSum(l,n),getSum(x,r)+getSum(r,n));
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 1;i<=n;i++)
            scanf("%lld",&arr[i]);
        sort(arr+1,arr+n+1);
        ll ans = INFF;
        sum[0] = 0;
        for(int i = 1;i<=n;i++)
            sum[i] = sum[i-1]+arr[i];
        for(int i = 1;i<=n-2;i++)
            ans = min(ans,sum[i]*i+trisearch(i));
        printf("%lld\n",ans);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值