ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CodeForce div2 Round #763

2022-01-04 19:02:33  阅读:194  来源: 互联网

标签:le int 763 ll mid 枚举 CodeForce 答案 Round


C-Balanced Stone Heaps

  • 题目描述:给定\(n\)堆石子,规定第\(i(3\le i\le n)\)堆石子能够能够从中取出\(3d\)个石子(\(0<3d<h_i\),其中\(h_i\)为第\(i\)堆石子的数量),其中\(d\)个石子放入第\(i-1\)堆,\(2d\)个石子放入第\(i-2\)堆石子之中,我们从第\(3\)个石子往第\(i\)个石子遍历一次,问所有堆中石子数目最少的堆的石子数目最多是多少
  • 求解“最少中最多”和“最多中最少”问题,我们显然可以联想到二分答案,而本题的关键之处便是在于如何对枚举的答案进行检验
  • 正向考虑这个问题,对于第\(i(2\le i\le n-2)\)个位置,我们总是有两个来源,而如何从这两个来源中进行分配,,以拼凑出当前枚举的答案\(x\)相对较难考虑
  • 所以我们逆向考虑这个问题,从第\(n\)个元素向前考虑, 每个元素扣除一定份额向前分配,要匹配枚举出的答案\(x\)相对容易,所以我们在检验答案时逆向考虑
  • 而逆向考虑还有一个注意点,对于当前位置\(i\),我们有原本石子数\(h_i\)和增量\(b_i\),由于我们是自前向后遍历,所以我们只能利用原本石子数\(h_i\)来向前分配,而增量是无法用以向前分配的
  • 所以我们在\(b_i\)小于\(x\)时,我们判断\(h_i+b_i\)是否大于枚举答案\(x\),当大于时,我们从\(h_i\)中扣除\(x-b_i\)部分使得其能满足标准答案\(x\),剩余\(h_i\)部分尽可能进行分配
  • 如果是小于,我们可以直接认为这个答案不可取,因为对于第\(i\)个元素已经不可能满足,直接\(break\)即可
  • 最后因第\(1,2\)个元素无需向前分配,对其作特殊判断即可
  • 本题中还有一个关键要点,增量\(b_i\)如果使用数组进行存储的话,每次检查时都需要\(memset\),这会导致较大的时间复杂度,并在第二个测试样例超时,所以我们使用向量来存储增量,并在每次检查时根据元素数量进行定义
  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn =2e5+5;
#define ll long long
// 二分答案
// 如何进行检验?
// 检验方法是本道题的关键

int T,n;
ll a[maxn];

int check(int x){
    int flag=0;
    vector<int> b(n+10);
    // 本题卡memset,
    for(int i=n;i>=3;i--){
        if(b[i]>=x){
            ll t=a[i]/3;
            b[i-1]+=t;
            b[i-2]+=2*t;
        }else if(a[i]+b[i]>=x){
            ll t=(a[i]-(x-b[i]))/3;
            b[i-1]+=t;
            b[i-2]+=2*t;
        }else{
            flag=1;
            break;
        }
    }
    if(a[1]+b[1]<x||a[2]+b[2]<x)flag=1;
    return !flag;

}

int main(){
    cin>>T;
    while(T--){
        cin>>n;
        ll minx=1e9,maxx=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            minx=min(minx,a[i]);
            maxx=max(maxx,a[i]);
        }
        ll l=minx,r=maxx;
        ll ans;
        while(l<=r){
            ll mid=(l+r)>>1;
            if(check(mid)){
                ans=mid;
                l=mid+1;
            }else r=mid-1;
        }
        cout<<ans<<endl;
    }

    return 0;
}

标签:le,int,763,ll,mid,枚举,CodeForce,答案,Round
来源: https://www.cnblogs.com/Ghaser/p/15763639.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有