码迷,mamicode.com
首页 > 其他好文 > 详细

CF505E

时间:2020-12-07 12:27:23      阅读:5      评论:0      收藏:0      [点我收藏+]

标签:amp   tps   ret   pre   保存   www   等于   top   最小   

CF505E

给定 n 个数 h1…n?。
你需要进行 m 轮操作,
每轮操作为 k 次修改,每次修改可以选择一个数 hi? 修改为 max(hi??p,0)。
每轮操作后每个hi? 将会被修改为 hi ?+ ai?。
你需要最小化最终 h1…n? 中的最大值。
n ≤ 1e5,m≤5e3,k ≤ 10。

=========================================================

二分最大值
正着不好做,考虑倒序
即,n 个竹子,最后高度为 min_h ,每轮会砍一刀,每次你可以拔 p 的高度,
最后的高度大于等于 h[i]
code

bool check(int mid)
{
    priority_queue <PII,vector<PII>,greater<PII> > que;
    for(int i = 1;i <= n;i ++)
    {
        c[i] = 0;//顺便初始化,在下面的代码中表示这个竹子已经被拔高了 c[i] 次了
        if(h[i] + a[i] * m <= mid) continue; //不用考虑
        que.push({mid / a[i],i}); //保存几次就砍没了 
    }
    int cnt = 0;//记录拔的次数 
    for(int i = 1;que.size() && i <= m;i ++)
        for(int j = 1;que.size() && j <= k;j ++)
        {
            if(que.top().first < i) return false; //前 i 轮就砍没个球了,说明当前高度太小
            int x = que.top().second;
            que.pop();
            int w = (mid + (++ c[x]) * p) / a[x];//这次就拔一下它,因为这是最可能目前凉凉的,然后计算出最多可以砍几轮 
            if(w < m)  // m 轮之内还可能会凉凉,还得再拔一下 
                que.push({w,x});
            cnt ++;//记录拔的次数 
        }
    for(int i = 1;i <= n;i ++)
    {
        if(h[i] + a[i] * m <= mid) continue;//这个不用鸟 
        int w = mid - a[i] * m + c[i] * p;//
        if(h[i] <= w) continue;
        //
        w = ceil((double)(h[i] - w) / p);
        cnt += w;
        if(cnt > m * k) return false; 
         
    }
    return true;
}

====================================================================

CF505E

标签:amp   tps   ret   pre   保存   www   等于   top   最小   

原文地址:https://www.cnblogs.com/xy0313/p/14072847.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!