天天看點

2020牛客國慶集訓派對day3(補題)

補題J:Flowers

題目連結

tot(為花的貢獻和)

本題給出資料n,m,n為花卉種類,m為每束花應該有m種,check中的x為x束花,假設有x束花,則應該有xm朵花,在n種花中,(check過程)如果a[i]>x則說明花的數量大于花束的數量,這種花可以用在每一種,而且還多出來,tot中加上x,反之第i種花的數量小于花束的數量則tot應該加上該種花的數量(a[i])。如果tot最終大于xm則花的貢獻量大于應該有的花數,則check函數傳回1(最佳答案大于等于x也就是傳過去的mid),使ans值等于mid并使左邊界等于mid+1,反之如果tot<x*m,則說明花的貢獻量小于應有的花數,則check傳回0(最佳答案小于等于x),使右邊界等于mid-1。(二分過程)。

代碼:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#include<sstream>
#include<memory>
#include<functional>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a));
#define ll long long int
const int INF = 0x3f3f3f3f;
int n,m;
ll a[300030];
bool check(ll x)//x束
{
    ll tot=0;//tot是花的貢獻和
    for(int i=0;i<n;++i)
        tot+=min(a[i],x);//a[i]>=x,該花可以用在每一束,則取x,a[i]<x,該花不能用在每一束,取該花的數量(該種花需要全部用完)
    if(tot>=x*m)
        return 1;
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        ll sum=0;
        for(int i=0;i<n;++i)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        ll l=0,r=sum/m,ans;//r是右邊界
        while(l<=r)
        {
                ll mid=(l+r)>>1;
                if(check(mid))
                {
                    l=mid+1;
                    ans=mid;
                }
                else
                    r=mid-1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

           

繼續閱讀