Bouquet-Codeforces Round 961 (Div. 2)B2

题目大意:
有m块钱,买花只能买花瓣数差值不超过1的花,有多少花瓣就花多少钱,问最多能买到多少花瓣

分析:
赛时的时候就觉得是一个分类讨论,可惜没讨论出来,
策略是先只买一种,取 m a x max max,如果存在 x + 1 x+1 x+1的花瓣数,先看能不能都买光.
如果不能买光,先买花瓣数为 x x x的,买的个数是 g 0 = m i n ( m / x , c [ x ] ) g0 = min(m/x,c[x]) g0=min(m/x,c[x])代表着最多能买的个数和有的个数的最小值,
钱还有剩下的话买花瓣数为 x + 1 x+1 x+1的花,同理买 g 1 = m i n ( c [ x + 1 ] , ( m − x ∗ g 0 ) / ( x + 1 ) ) g1 = min(c[x+1],(m-x*g0)/(x+1)) g1=min(c[x+1],(mxg0)/(x+1))这么多,代表着有的花,和能买的花的最小值。
计算一下这样买了之后还剩下的钱 l e f t left left,如果说当前还可以买的花(花瓣数为x+1)和已经买的x的花大于等于left,说明可以用x+1代替x把钱花完,所以答案就是m
如果不可以的话,就替代min(g0,c[x+1]-g1),可能被替代的x和可以用来替代的x+1的最小值,答案取max

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

int n;i64 m;
void solve(){
    cin>>n>>m;
    vector<pair<i64,i64>> a(n);
    for(int i = 0;i<n;++i) cin>>a[i].first;
    for(int i = 0;i<n;++i) cin>>a[i].second;
    sort(a.begin(),a.end());
    i64 ans = 0;
    for(int i = 0;i<n;++i){
        ans = max(ans,min(m/a[i].first*a[i].first,a[i].first*a[i].second));
        if(i+1<n&&a[i].first+1==a[i+1].first){
            i64 r1 = a[i].first*a[i].second+a[i+1].first*a[i+1].second;
            if(r1<=m) ans = max(ans,r1);
            else{
                i64 g0 = min(a[i].second,m/a[i].first);
                i64 g1 = min(a[i+1].second,(m-g0*a[i].first)/a[i+1].first);
                i64 left = m-g0*a[i].first-g1*a[i+1].first;
                if(a[i+1].second-g1>=left&&g0>=left){
                    ans = max(ans,m);
                }else{
                    r1 = m-left+min(g0,a[i+1].second-g1);
                    ans = max(ans,r1);
                }
            }
        }
    }
    cout<<ans<<'\n';
}

signed main(){
    ios;
    int t;cin>>t;
    while(t--){
        solve();
    }
    return 0;
}



Easy版本:
easy版本我写了个长度为2的滑动窗口,限制条件有不超过m元,差值不为一,所以只要排个序,再写一个滑动窗口即可,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)因为有排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值