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

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;
}

猜你喜欢

转载自blog.csdn.net/sudu6666/article/details/88399410