Codeforces Round #560 (Div. 3) F1. F2.Microtransactions

F1的题目链接

F2的题目链接

题目大意

AA现在有n种装备要买,每个装备要买ki个,每一天的早上AA会赚到1元钱,每个装备的价钱都是2元,但是现在有m个特价活动(d1,ti)意思是在di天的时候第ti个装备只要1元钱,问你买完所有的装备所需的最小天数是多少?
F1 和 F2的题是一样的,只是数据范围不一样,我用的方法都是二分(log的时间复杂度)所以两个题的代码是一样的,都可以过。

解题思路

其实这个是一道二分题,和之前做的一个题晾衣服的题好像差不多,奈何我这个鱼脑子… …怎么就不长记性… … …
我们二分需要的天数,最小需要一天,最多需要的是每个装备都化2元钱要tot*2天,这里还是很好理解的,主要是怎么去判断mid天内能不能卖完这些装备呢:
我们设ans是现在有的钱,xi是第i个装备现在还有多少个没有买,那么钱就等于天数。我们先考虑可以特价买的商品的数量,因为能特价买的就特价买嘛,如果不能特价买就话2元买,这里感觉是个贪心:我们把能再mid天内搞特价的都存起来,然后按天数从小到大排序,一个个判断现在的钱够买多少个当前装备,xi减去能买的相应的数量,到最后xi剩的就是要两元买的数量了,用当前的钱数减去,如果最后的钱还大于等于0,就是可以买,否则就是不能买

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[500005],x[500005];
struct node
{
    int d,t;
};
node e[500005],c[500005];
int n,m;
int cmp(node w,node p)
{
    return w.d<p.d;
}
int F(int mid)
{
    for(int i=1;i<=n;i++)
    {
        c[i].d=0;
        c[i].t=i;
    }
    for(int i=1;i<=n;i++)
        x[i]=a[i];
    for(int i=1;i<=m;i++)
    {
        if(e[i].d<=mid)
        {
            int h=e[i].t;
            c[h].d=max(c[h].d,e[i].d);
        }
    }
    sort(c+1,c+1+n,cmp);
    int ans=0,k=0;//k是上一次用钱的那天
    for(int i=1;i<=n;i++)//贪心
    {
        int s=c[i].t;
        ans+=c[i].d-k;
        k=c[i].d;
        if(ans>=x[s])
        {
            ans-=x[s];
            x[s]=0;
        }
        else
        {
            x[s]-=ans;
            ans=0;
        }
    }
    if(k<mid)
        ans+=(mid-k);
    for(int i=1;i<=n;i++)
       ans-=(x[i]*2);
    return ans>=0;
}
int main()
{
    int tot=0;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        tot+=a[i];
    }
    for(int i=1;i<=m;i++)
     scanf("%d %d",&e[i].d,&e[i].t);
     int l=1,r=tot*2,ans=0x3f3f3f3f;
     while(l<=r)
     {
         int mid=(l+r)/2;
         if(F(mid))
         {
             ans=min(ans,mid);
             r=mid-1;
         }
         else
            l=mid+1;
     }
     printf("%d\n",ans);
     return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值