Educational Codeforces Round 61 (Rated for Div. 2) D. Stressful Training(贪心+二分)

本文解析了Educational Codeforces Round 61中的一道难题,涉及二分查找与贪心算法的结合应用,提出了两种算法实现方案,分别以事件堆和桶排序为核心,用于解决电脑电量维持的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Educational Codeforces Round 61 (Rated for Div. 2)

题意:有n台电脑要使用,一共m分钟,每台电脑初始电量ai,每分钟消耗bi,若你有一台充电宝,那么每分钟至少冲多少电量,才能保证每分钟所有电脑的电量都是>=0。

题解:首先根据题意可以很清楚的看出来应该可以二分,因为若答案x可行,则答案x+1一定可行(显然 :) ),但是如何check答案是一个难点,这里我们可以用贪心算法,每次充电都给最早没电的电脑冲,这显然是正确的,那么我们这里有两种算法进行实现:

Solve 1: O((n+m)lg^2(n)) 首先我们可以考虑有一个事件堆来维护,维护每一个事件没电的那一天就可以了,实现比较简单,但是复杂度偏高。

Solve 2:O((n+m)lg(n)) 其实对于m来说数据并不是很大,2e5,所以我们可以考虑进行桶排序,用lis[i]来保存第i天没电的电脑的下标,然后一天一天的枚举,然后维护即可~~~

#include<bits/stdc++.h>
using namespace std;
#define Sheryang main
const int maxn=1e6+7;
typedef long long ll;
const int mod=1e9+7;
void Smax(int &a,int b){if(a<b) a=b;}
void Smin(int &a,int b){if(a>b) a=b;}
///#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
///char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
#define IO cin.tie(0),ios::sync_with_stdio(false);
#define pi acos(-1)
#define PII pair<ll,ll>
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}
#define read read()
/** keep hungry and keep calm! **/

ll a[maxn],b[maxn];
ll n,m;

struct node{
    ll a,b,c;
    bool operator <(const node &a)const{
        return a.c<c;
    }
};

bool judge(ll x){
    priority_queue<node>q;
    for(int i=1;i<=n;i++){
        q.push({a[i],b[i],a[i]/b[i]});
    }
    for(int i=1;i<=m;i++){
        node t=q.top();q.pop();
        if(t.c<i-1) return false;
        if(t.c>=m) return true;
        q.push({t.a+x,t.b,(t.a+x)/t.b});
    }
    return true;
}


int Sheryang()
{
    n=read,m=read;

    for(int i=1;i<=n;i++){
        a[i]=read;
    }
    for(int i=1;i<=n;i++){
        b[i]=read;
    }

    ll l=0,r=1e14,ans=-1;
    while(l<=r){
        ll mid=(l+r)/2;
        if(judge(mid)){
            ans=mid;
            r=mid-1;
        }else{
            l=mid+1;
        }
    }

    printf("%lld\n",ans);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define Sheryang main
const int maxn=1e6+7;
typedef long long ll;
const int mod=1e9+7;
void Smax(int &a,int b){if(a<b) a=b;}
void Smin(int &a,int b){if(a>b) a=b;}
///#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
///char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
#define IO cin.tie(0),ios::sync_with_stdio(false);
#define pi acos(-1)
#define PII pair<ll,ll>
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}
#define read read()
/** keep hungry and keep calm! **/

ll a[maxn],b[maxn],cur[maxn];
ll n,m;

vector<int>lis[maxn];
bool judge(ll x){
    for(int i=0;i<m;i++){
        lis[i].clear();
    }
    for(int i=0;i<n;i++){
        ll t=a[i]/b[i]+1;
        cur[i]=a[i]%b[i];
        if(t<m){
            lis[t].push_back(i);
        }
    }

    int now=1;
    for(int i=0;i<m;i++){
        while(now<m && lis[now].empty()){
            now++;
        }

        if(now==m) return true;
        if(now<=i) return false;

        int t=lis[now].back();
        if(cur[t]+x<b[t]){
            cur[t]+=x;
            continue;
        }
        lis[now].pop_back();
        ll nt=(cur[t]+x)/b[t];
        cur[t]+=x;cur[t]%=b[t];
        if(nt+now<m){
            lis[now+nt].push_back(t);
        }
    }
    return true;
}


int Sheryang()
{
    n=read,m=read;

    for(int i=0;i<n;i++){
        a[i]=read;
    }
    for(int i=0;i<n;i++){
        b[i]=read;
    }

    ll l=0,r=1e14,ans=-1;
    while(l<=r){
        ll mid=(l+r)/2;
        if(judge(mid)){
            ans=mid;
            r=mid-1;
        }else{
            l=mid+1;
        }
    }

    printf("%lld\n",ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值