F. Bomb

纯粹的發表於2024-07-27

原題連結

題解

貪心的每次挑選當前最大的,但是要挑選k次,因此我們沒法去遍歷挑選的過程,因此我們考慮最終形態,由於每次挑選最大的元素,因此最後所有數一定不超過某個數,二分由此而來

code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,k;

ll a[200005],b[200005];

ll check(ll x)
{
    ll res=0;
    for(ll i=1;i<=n;i++)
    {
        if(a[i]>x)
        {
            res+=(a[i]-x)/b[i]+((a[i]-x)%b[i]!=0);
        }
    }
    return res;
}

ll cal(ll x)
{
    //printf("x:%lld\n",x);
    ll ans=0;
    ll tem=k;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>x)
        {
            ll num=min((a[i]-x)/b[i]+((a[i]-x)%b[i]!=0),tem);
            //printf("ai:%lld  bi:%lld  num:%lld\n",a[i],b[i],num);
            ans+=a[i]*num-num*(num-1)/2*b[i];
            a[i]-=num*b[i];
            tem-=num;
        }
    }

    for(ll i=1;i<=n;i++)
    {
        if(!tem) break;
        if(a[i]==x)
        {
            ans+=x;
            tem--;
        }
    }
    return ans;
}

void solve()
{
    cin>>n>>k;

    for(ll i=1;i<=n;i++) cin>>a[i];
    for(ll i=1;i<=n;i++) cin>>b[i];

    ll l=-1,r=1e9;
    while(l+1<r)
    {
        ll mid=(l+r)/2;
        if(check(mid)<=k) r=mid;
        else l=mid;
    }

    cout<<cal(r)<<'\n';
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--) solve();
    return 0;
}