• 寒假集训Day6 H(二分答案)


    题目链接在这里:Problem - H - Codeforces

    我们首先来看如果正着做的话,需要有一些高位的数降到0来补充,但是我们不知道哪几个高位的数需要降,如果每降一个高位来重新计算一下结果的话很显然是会超时的。我们可以发现,如果当前位的数要降的话,比它高的位也是要降的。这样我们可以二分这个要降的位,争取把每次查询的时间复杂度化简到O(N)的级别。

    很显然我们能观察到这里哪一个数降不降和答案其实是等价的。

    然后我们去考虑检验结果的问题。如果正着做的话我们会遇到一些困难,所以考虑倒着去做,由结果推到给定状态,也就是从结果位一个一个推到第一位,只要能推出是初始状态的子集就行了。如果当前位减一的话,相当于前面的每一位都要加一,这对前面的每一位都是等价的,所以说我们可以用一个变量去维护,然后往回推。可以发现,如果对于初始状态来说当前位一直是0的话,个数是以指数形式增长的,所以我们需要增加一个判断条件,如果当前位的个数超过了总共初始状态的1的个数就跳。

    这里如果一个数>x 它就变成0;如果一个数小于x 它就会让比它小的每一个数都至少加1。

    如果推到0以后多的位能补回到之前缺的位上,那么就是可行的,如果0多了,说明达到当前结果需要更多比当前结果大的数来变为0,所以是不可行的。

    参考代码:

     1 #include "bits/stdc++.h"
     2 using namespace std;
     3 typedef long long LL;
     4 const int MAX=100105;
     5 LL n,a[MAX],b[MAX],mx;
     6 bool feasible(LL x){
     7     LL i,j;
     8     LL now,le,xx,yy;
     9     now=1,le=b[x];
    10     for (i=x-1;i>=1;i--){
    11         if (now>b[0]) return false;
    12         if (now==a[i]) continue;
    13         if (now<a[i]){
    14             le+=a[i]-now;
    15             continue;
    16         }
    17         if (now>a[i]){
    18             now=now+(now-a[i]);
    19             continue;
    20         }
    21     }
    22     if (now-a[0]<=le) return true;
    23     else return false;
    24 }
    25 int main(){
    26 //    freopen ("h.in","r",stdin);
    27 //    freopen ("h.out","w",stdout);
    28     LL i,j;
    29     LL low,high,mid,ans;
    30     scanf("%lld",&n);
    31     memset(a,0,sizeof(a));
    32     for (i=0;i<n;i++) scanf("%lld",a+i);
    33     b[n+1]=0;
    34     for (i=n-1;i>=0;i--)
    35         b[i]=a[i]+b[i+1];
    36     if (b[0]==1){
    37         if (a[0]==1 || a[1]==1) printf("1");
    38         else{
    39             i=2;
    40             while (a[i]==0) i++;
    41             printf("%lld",i);
    42         }
    43         return 0;
    44     }
    45     
    46     low=1;high=100100ll;
    47     while (low<=high){
    48         mid=(low+high)>>1;
    49         if (feasible(mid)){
    50             ans=mid;
    51             low=mid+1;
    52         }
    53         else high=mid-1;
    54     }
    55     printf("%lld",ans);
    56     return 0;
    57 }
  • 相关阅读:
    SQL中 patindex函数的用法
    纵表与横表互转的SQL
    几种数据库的大数据批量插入【转】
    使用cmd命令行窗口操作SqlServer
    C#性能优化实践
    C# 图像处理(二)—— 黑白效果
    SQLSERVER系统视图
    SQLServer行列转换 Pivot UnPivot
    C#图片处理常见方法性能比较
    GSM局数据制作1(Erision)
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/15824809.html
Copyright © 2020-2023  润新知