codeforces#1165 F2. Microtransactions (hard version) (二分+贪心)

题目链接:

https://codeforces.com/contest/1165/problem/F2

题意:

需要买$n$种物品,每种物品$k_i$个,每个物品需要两个硬币

每天获得一个硬币

有$m$个优惠

在$d_i$天,$t_i$物品卖一个硬币

求购买所需物品最少需要的天数

数据范围:

$1 \le n, m \le 2 \cdot 10^5$

分析: 

我们可以注意到,如果某天是某个物品的最后优惠时间,那么我们一定要在这天尽可能多地购买这个物品

对答案进行二分

再二分得到每个物品在这个答案下的最后优惠时间

贪心购买每种物品

复杂度$O(lgn*lgn*n)$

ac代码:

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const int maxn=2e5+10;
const ll mod=998244353;
vector<int>ve[maxn];
int sale[maxn*10],sum,num[maxn],n,m;
bool check(int day)//检查天数为day时,能不能买完所以需要的东西
{
    for(int i=1;i<=day;i++)sale[i]=0;//购买最后期限为i的物品数量
    for(int i=1;i<=n;i++)
    {
        if(ve[i].size()==0)continue;
        int st=0,en=(int)ve[i].size()-1;//二分每种物品的最后期限
        while(st!=en)
        {
            int md=(st+en)/2;
            if(ve[i][md+1]<=day)st=md+1;
            else en=md;
        }
        sale[ve[i][st]]+=num[i];
    }
    int money=0,buy=0;
    for(int i=1;i<=day;i++)//只要是最后期限,那么这个物品我们就买最多
    {
        money++;
        buy+=min(money,sale[i]);
        money-=min(money,sale[i]);
    }
    if(money>=2*(sum-buy))return 1;
    else return 0;
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
        sum+=num[i];
    }
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        ve[b].push_back(a);
    }
    for(int i=1;i<=n;i++)
        sort(ve[i].begin(),ve[i].end());
    
    int st=sum,en=2*sum;//对答案二分
    while(st!=en)
    {
        int md=(st+en)/2;
        if(check(md))en=md;
        else st=md+1;
    }
    printf("%d\n",st);
    return 0;
}

  

转载于:https://www.cnblogs.com/carcar/p/10905108.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值