Berland Fair CodeForces - 1073D(模拟题)

题意:n个数排成一个圆盘,一个人有T元钱,从第一个开始,只要他能买的,他一定会买,这样依次循环,直到他的钱不能买任何物品时结束,问,他能买多少件东西。

思路:按题意模拟即可,不过T太大,考虑优化,优化的方法是当n个数的最大值都比T小,并且n个数的sum也小于T时,我们直接一次性买n个即可。

当最大值大于T时,显然这个物品永远都不会被买到,直接丢弃即可。

最后一种情况,当最大值小于T,但是sum大于T时,直接O(n)模拟买一次即可。

具体实现利用multiset来维护,很方便。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n;
ll a[maxn];
ll T;
multiset<ll> se;
multiset<ll>::iterator it;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    //scanf("%d",&n,&T);
    cin>>n>>T;
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        //scanf("%lld",a[i]);
        cin>>a[i];
        sum+=a[i];
       // printf("%lld\n",a[i]);
       se.insert(-a[i]);
    }
    //printf("11\n");
    ll ans=0;
    while(T>0&&se.size())
    {
        it=se.begin();
        //printf("%d %lld\n",T,sum);
        // cout<<T<<"  "<<sum<<endl;
        if(abs(*it)<=T&&sum<=T)
        {
            //cout<<1<<endl;
            ll tmp=T/sum;
            T-=tmp*sum;
            ans+=tmp*se.size();
        }
        else if(abs(*it)<=T&&sum>T)
        {
            for(int i=1;i<=n;i++)
            {
                if(se.find(-a[i])==se.end()) continue;
                if(a[i]<=T)
                {
                    T-=a[i];
                    ans++;
                }
                if(T<0) break;
            }
        }
        else
        {
            //cout<<2<<endl;
            ll tmpp=*it;
            se.erase(it);
            sum+=tmpp;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40774175/article/details/83784691