zoukankan      html  css  js  c++  java
  • 暑假考试题4:砍树 cut(整除分块)

     

    题目:

    分析:

    一看这道题,诶不就二分一个d去O(n)地check不就可以了吗?

    但其实是不能二分的!!因为不满足单调性。比如这组数据:a[ i ]=4  k=1   当d=3时,会在第6天砍,cost=2,d=4时,会在第4天砍,cost=0,明显d更大了,反而更优了!!!

    所以说二分之前一定要考虑是否满足单调性,当自认为满足时,还应该出一点反例(这道题里面出一个小的d不满足,大的反而满足)。

    那么不满足怎么办呢 ->从大到小枚举,枚举到的第一个满足的就break掉。d的上界是 min{ a[ i ] } + k (因为k>=d-minn)

    当然,会T掉。

    于是手推一下式子:

    而ai/d(上取整)会发现有重复的,于是考虑用整除分块 (整除分块的一般证明):如何整除分块

    下面是证明:

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 2100000000
    #define N 105
    #define ll long long
    ll k,minn=inf,ans,a[N],sum;
    int n;
    bool fl[N];
    int main()
    {
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        scanf("%d%lld",&n,&k);
        sum=k;
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i],minn=min(minn,a[i]);
        minn+=k;
        ll d=1;
        while(1){
            ll tot=0;
            for(int i=1;i<=n;i++){
                if(a[i]%d) tot+=(a[i]/d +1)*d;//讨论能不能整除 从而向上取整 
                else tot+=a[i]; 
            }
            if(tot<=sum) ans=d;
            if(d>=minn) break;
            d=sum/(sum/(d+1));
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    数据库索引的作用和长处缺点
    ping不通的几种可能原因
    UVA
    strtok、strtok_s、strtok_r 字符串切割函数
    CheckBoxPreference组件
    EM算法原理
    Android中ExpandableListView控件基本使用
    拓扑排序的原理及事实上现
    DropdownList绑定的两种方法
    leetcode第一刷_Length of Last Word
  • 原文地址:https://www.cnblogs.com/mowanying/p/11409070.html
Copyright © 2011-2022 走看看