zoukankan      html  css  js  c++  java
  • 【説明する】分治

    拉呱

    分治算法的基本思想是将一个规模为 N 的问题分解为 K 个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。

                      ——以上来自百度百科。

    * 分治法解题的一般步骤:
    1 分解,将要解决的问题划分成若干规模较小的同类问题;
    - 二分法:区间对半分开
    2 求解,当子问题划分得足够小时,用较简单的方法解决;
    - 边界情况:可以直接操作
    3 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。
    - 合并操作:根据不同的题目来确定

    例题:

    -------------------------------T1+T2-------------------------------

    其实这个题用冒泡排序做的,但用归并排序也能做出来(分析一下此题与逆序对是有相同之处的)

    由于两者的代码完全一样,就只放一个啦  (>^ω^<)喵

    1.洛谷 P1116 车厢重组

    题目描述

    在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。

    输入输出格式

    输入格式:

    输入文件有两行数据,第一行是车厢总数N(不大于10000),第二行是N个不同的数表示初始的车厢顺序。

    输出格式:

    一个数据,是最少的旋转次数。

    输入输出样例

    输入样例#1:
    4
    4 3 2 1 
    输出样例#1:
    6

    2.洛谷 P1908 逆序对

    题目描述

    猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。

    输入输出格式

     输入格式:

    第一行,一个数n,表示序列中有n个数。

    第二行n个数,表示给定的序列。

     输出格式:

    给定序列中逆序对的数目。

     输入输出样例

     输入样例#1:
    6
    5 4 2 6 3 1
    
     输出样例#1:
    11

    说明

    对于50%的数据,n≤2500

    对于100%的数据,n≤40000。

    思路:

         归并过程为:比较A[i]和A[j]的大小,若A[i]≤A[j],则将第一个有序表中的元素A[i]复制到R[k]中,并令i和k分别加1,即使之分别指问后一单元,否则将第二个有序表中的元素A[j]复制到R[k]中,并令j和k分别加1;如此循环下去,直到其中的一个有序表取完,然后再将另一个有序表中剩余的元素复制到R中从下标k到下标t的单元.
         归并排序算法我们用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。对左右子区间的排序与原问题一样,所以我们可以调用同样的子程序,只是区间大小不一样。

    代码酱来也~

    #include <iostream>
    #include <cstdio>
    #define LL long long 
    
    using namespace std;
    
    const int M = 4e4 + 1;
    int n;
    LL ans;
    int a[M],b[M];
    
    void gsort(int l,int r)
    {
        if(l==r) return;///不用再次排序
        int m=(l+r)>>1;///取中间 
        gsort(l,m),gsort(m+1,r);
        int i=l,j=m+1;
        int k=l;///将a数组的值赋值到b数组 
        while(i<=m && j<=r)
        {
            if(a[i]<=a[j])
                b[k++]=a[i++];///先赋值再++
            else
            {
                b[k++]=a[j++];///
                ans+=(LL)(m)-(LL)i+1;///记录当前所形成的逆序对的个数 
            }
        }
        while(i<=m) b[k++]=a[i++];///赋值剩余没有进行比较的 
        while(j<=r) b[k++]=a[j++];///
        for(int i=l;i<=r;i++)
            a[i]=b[i];///排完序后将排好序的在赋值回去 
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
         scanf("%d",&a[i]);
        gsort(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    --------------------------------T3--------------------------------

    3.Codevs 1688 求逆序对

    时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
    题目描述 Description

    给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目

    数据范围:N<=105。Ai<=105。时间限制为1s。

    输入描述 Input Description

    第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。

    输出描述 Output Description

    所有逆序对总数.

    样例输入 Sample Input

    4

    3

    2

    3

    2

    样例输出 Sample Output

    3

    数据范围及提示 Data Size & Hint

    思路:

      这题有毒!!!where is the 数据范围???
      这数据范围太大了有没有!!!所以int类型的就会炸,将int改为long long就ok了!
      这题我交了好几遍!

    代码酱来也~

    #include <iostream>
    #include <cstdio>
    #define LL long long 
    
    using namespace std;
    
    const int M = 1e5 + 1;
    int n;
    LL ans;
    int a[M],b[M];
    
    void gsort(int l,int r)
    {
        if(l==r) return;///不用再次排序
        int m=(l+r)>>1;///取中间 
        gsort(l,m),gsort(m+1,r);
        int i=l,j=m+1;
        int k=l;///将a数组的值赋值到b数组 
        while(i<=m && j<=r)
        {
            if(a[i]<=a[j])
                b[k++]=a[i++];///先赋值再++
            else
            {
                b[k++]=a[j++];///
                ans+=(LL)(m)-(LL)i+1;///记录当前所形成的逆序对的个数 
            }
        }
        while(i<=m) b[k++]=a[i++];///赋值剩余没有进行比较的 
        while(j<=r) b[k++]=a[j++];///
        for(int i=l;i<=r;i++)
            a[i]=b[i];///排完序后将排好序的在赋值回去 
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
         scanf("%d",&a[i]);
        gsort(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    --------------------------------T4--------------------------------

    4.洛谷 P1115 最大子段和

    题目描述

    给出一段序列,选出其中连续且非空的一段使得这段和最大。

    输入输出格式

    输入格式:

    输入文件maxsum1.in的第一行是一个正整数N,表示了序列的长度。

    第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列。

    输出格式:

    输入文件maxsum1.out仅包括1个整数,为最大的子段和是多少。子段的最小长度为1。

    输入输出样例

    输入样例#1:
    7
    2 -4 3 -1 2 -4 3
    输出样例#1:
    4

    说明

    【样例说明】2 -4 3 -1 2 -4 3

    【数据规模与约定】

    对于40%的数据,有N ≤ 2000。

    对于100%的数据,有N ≤ 200000。

    思路:

      这道题真的就是一道模板题,但是为什么我交了好几遍就是没有AC呢?

      原因出在第二个点上,因为第二个点里的数据似乎全部都是负的,所以在进行初始化的时候需要赋值为一个极小数(ans,lmax,rmax这三个)

      不然按一般的话,一定是从0开始,所以负数就出不来,所以……

    代码酱来也~

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #define LL long long 
    
    using namespace std;
    
    const int M = 2e5 + 233;
    int n;
    LL ans;
    int a[M];
    
    LL calc(int l,int r)
    {
        if(l==r) return a[l];///不用再次排序
        int m=(l+r)>>1;///取中间
        LL ret=max(calc(l,m),calc(m+1,r)); 
        
        /* find the maxl and maxr */
        int maxl=-1e6,maxr=-1e6;
        for(int i=m,s=0;i>=l;i--) s+=a[i],maxl=max(maxl,s);
        for(int i=m+1,s=0;i<=r;i++) s+=a[i],maxr=max(maxr,s);
        ret=max(ret,(LL)(maxl)+(LL)(maxr));
        return ret;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
         scanf("%d",&a[i]);
        ans=-1e6;
        ans=max(ans,calc(1,n));
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    --------------------------------T5--------------------------------

    5.洛谷P1010 幂次方

    题目描述

    任何一个正整数都可以用2的幂次方表示。例如

        137=2^7+2^3+2^0         

    同时约定方次用括号来表示,即a^b 可表示为a(b)。

    由此可知,137可表示为:

        2(7)+2(3)+2(0)

    进一步:7= 2^2+2+2^0 (2^1用2表示)

        3=2+2^0   

    所以最后137可表示为:

        2(2(2)+2+2(0))+2(2+2(0))+2(0)

    又如:

        1315=2^10 +2^8 +2^5 +2+1

    所以1315最后可表示为:

        2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

    输入输出格式

    输入格式:

    一个正整数n(n≤20000)。

    输出格式:

    符合约定的n的0,2表示(在表示中不能有空格)

    输入输出样例

    输入样例#1:
    1315
    输出样例#1:
    2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

    思路:

      如果遇到2或者1,特判一下,直接输出,其余的如果能够继续分解,就将其分解(分治~)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    
    void work(int n)
    {
        if(n==1)
        {
            printf("2(0)");
            return;
        }
        if(n==2)
        {
            printf("2");
            return;
        }
        else
        {
            int j=1,i=0;
            do
            {
                j*=2;
                if(j>n)///超出该数n 
                {
                    j/=2;
                    if(i==1) printf("2");///特判 
                    else
                    {
                        printf("2(");///输出形式 
                        work(i);
                        printf(")");
                    }
                    if(n-j!=0)///若还能够继续分解 
                    {
                        printf("+");///用+连接 
                        work(n-j);///继续分解 
                    }
                    return;
                }
                else i++;///如果还不够大,继续加 
            }while(1);
        }
    }
    
    int main()
    {
        int n;
        cin>>n;
        work(n);
        return 0;
    }
    View Code

    --------------------------------T6--------------------------------

    6.P1024 一元三次方程求解

    题目描述

    有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。

    提示:记方程f(x)=0,若存在2个数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1,x2)之间一定有一个根。

    输入输出格式

    输入格式:

    一行,4个实数A,B,C,D。

    输出格式:

    一行,三个实根,并精确到小数点后2位。

    输入输出样例

    输入样例#1:
    1 -5 -4 20
    
    输出样例#1:
    -2.00 2.00 5.00

    思路:

      这题是一个很典型的数学问题,用二分法求零点(虽然有公式可以用,但是暴力枚举每个数也能过)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #define Db double
    
    using namespace std;
    
    Db a,b,c,d;
    
    Db f(Db x)
    {
        return a*x*x*x+b*x*x+c*x+d;
    }
    
    Db works(int x,int y)
    {
        Db x1=(Db)(x),x2=(Db)(y);
        Db mid=(x1+x2)/2,t1,t2;
        while(x1<=x2)
        {
            t1=f(mid);
            t2=f(x1);
            if(t1*t2<=0) x2=mid-0.0001;
             else x1=mid+0.0001;
            mid=(x1+x2)/2;///更新 
        }
        return mid;
    }
    
    int main()
    {
        scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
        Db f1,f2;
        for(int v=-100;v<=100;v++)
        {
    //        f1=a*v*v*v+b*v*v+c*v+d;
            f1=f(v);
    //        f2=a*(v+1)*(v+1)*(v+1)+b*(v+1)*(v+1)+c*(v+1)+d;
            f2=f(v+1);
            if(f1==0) printf("%.2lf ",Db(v));
            if(f1*f2<0)
            {
                Db ans=works(v,v+1);
                printf("%.2lf ",ans);
            }
        }
        return 0;
    }
    View Code

    --------------------------------T7--------------------------------

    7.luogu P1083 借教室

    题目描述

    在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。

    面对海量租借教室的信息,我们自然希望编程解决这个问题。

    我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室。

    我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提

    供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。

    借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。

    现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。

    输入输出格式

    输入格式:

    第一行包含两个正整数n,m,表示天数和订单的数量。

    第二行包含n个正整数,其中第i个数为ri,表示第i天可用于租借的教室数量。

    接下来有m行,每行包含三个正整数dj,sj,tj,表示租借的数量,租借开始、结束分别在

    第几天。

    每行相邻的两个数之间均用一个空格隔开。天数与订单均用从1开始的整数编号。

    输出格式:

    如果所有订单均可满足,则输出只有一行,包含一个整数 0。否则(订单无法完全满足)

    输出两行,第一行输出一个负整数-1,第二行输出需要修改订单的申请人编号。

    输入输出样例

    输入样例#1:
    4 3 
    2 5 4 3 
    2 1 3 
    3 2 4 
    4 2 4
    输出样例#1:
    -1 
    2

    说明

    【输入输出样例说明】

    第 1 份订单满足后,4 天剩余的教室数分别为 0,3,2,3。第 2 份订单要求第 2 天到

    第 4 天每天提供 3 个教室,而第 3 天剩余的教室数为 2,因此无法满足。分配停止,通知第

    2 个申请人修改订单。

    【数据范围】

    对于10%的数据,有1≤ n,m≤ 10;

    对于30%的数据,有1≤ n,m≤1000;

    对于 70%的数据,有1 ≤ n,m ≤ 10^5;

    对于 100%的数据,有1 ≤ n,m ≤ 10^6,0 ≤ ri,dj≤ 10^9,1 ≤ sj≤ tj≤ n。

    NOIP 2012 提高组 第二天 第二题

    思路:

      二分答案水过2333

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int M = 1e6 + 8;
    int n,m;
    int ma[M],sum[M];
    int d[M],s[M],e[M];
    
    bool calc(int mid)
    {
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=mid;i++)
        {
            sum[s[i]]+=d[i];///表示从开始时间往后租借多少天 
            sum[e[i]+1]-=d[i];
        }
        ///特判 
        if(sum[1]>ma[1]) return 1;///表示第一天就不够租借了 
        for(int i=2;i<=n;i++)
        {
            sum[i]+=sum[i-1];///前缀和,表示前几天一共有多少需要被租借
            if(sum[i]>ma[i])///如果不够了
                return 1; 
        }
        return 0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&ma[i]);
    //        sum[i]=ma[i]+sum[i-1];
        }
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&d[i],&s[i],&e[i]);
        int l=1,r=m;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(calc(mid)) r=mid;///记录下出现差错的编号 
            else l=mid+1;
    ///让修改的人的编号再大一点,知道找出不成功的编号或者最终的成功 
        }
        if(m!=r)
        {
            printf("-1
    ");
            printf("%d",r);
        }
        else printf("0
    ");
        return 0;
    }
    View Code

    --------------------------------T8--------------------------------

    8.luogu P2678 跳石头

    题目背景

    一年一度的“跳石头”比赛又要开始了!

    题目描述

    这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达 终点。

    为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石)。

    输入输出格式

    输入格式:

    输入文件名为 stone.in。

    输入文件第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终 点之间的岩石数,以及组委会至多移走的岩石数。

    接下来 N 行,每行一个整数,第 i 行的整数 Di(0 < Di < L)表示第 i 块岩石与 起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同 一个位置。

    输出格式:

    输出文件名为 stone.out。 输出文件只包含一个整数,即最短跳跃距离的最大值。

    输入输出样例

    输入样例#1:
    25 5 2 
    2
    11
    14
    17 
    21
    输出样例#1:
    4

    说明

    输入输出样例 1 说明:将与起点距离为 2 和 14 的两个岩石移走后,最短的跳跃距离为 4(从与起点距离 17 的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。

    另:对于 20%的数据,0 ≤ M ≤ N ≤ 10。 对于50%的数据,0 ≤ M ≤ N ≤ 100。

    对于 100%的数据,0 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,000。

    思路:

      这道题可以用二分答案+贪心来做

      首先我们定义l为0,r为给出的起点终点之间的长度,然后用二分答案做,将枚举到的答案检查一下是否行得通;

      若行得通,继续寻找更优的答案,若行不通,寻找更小的答案;

      二分答案是很好想的,也很好写,但是问题是check数组不太好想

      我们根据题目的意思可以得到最多取走的石子数为m,所以如果当前答案已经给确定,但根据这个答案求出的最终取走的石子数要大于m,那么当前答案不成立

      如何判断是否能被取走呢?因为题目为最短距离最大,所以只需判断从上一块石头跳到当前石头的距离是否比答案大即可;

      如果大于,就跳上去,因为给出d数组是按照距离远近来的;反之若小于,就将这块石头取走,因为不满足题意.这既为check函数

    代码:

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    const int M = 5e4 + 1;
    int L,n,m;
    int d[M];
    
    bool check(int x)
    {
        int last=0;
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            if(d[i]-last<x)///make longer
                ans++;
            else 
                last=d[i];///record
        }
        if(ans>m)///if out of range 
            return 0;
        return 1;
    }
    
    int main()
    {
        scanf("%d%d%d",&L,&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&d[i]);
        int l,r,mid;
        l=0,r=L;
        while(l<=r)
        {
            mid=(l+r)/2;
            if(check(mid))
                l=mid+1;
            else
                r=mid-1;
        }
        printf("%d
    ",l-1);
        return 0;
    }
    View Code

    --------------------------------T9--------------------------------

    9.luogu P1182 数列分段Section II

    题目描述

    对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小。

    关于最大值最小:

    例如一数列4 2 4 5 1要分成3段

    将其如下分段:

    [4 2][4 5][1]

    第一段和为6,第2段和为9,第3段和为1,和最大值为9。

    将其如下分段:

    [4][2 4][5 1]

    第一段和为4,第2段和为6,第3段和为6,和最大值为6。

    并且无论如何分段,最大值不会小于6。

    所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6。

    输入输出格式

    输入格式:

    输入文件divide_b.in的第1行包含两个正整数N,M,第2行包含N个空格隔开的非负整数A[i],含义如题目所述。

    输出格式:

    输出文件divide_b.out仅包含一个正整数,即每段和最大值最小为多少。

    输入输出样例

    输入样例#1:
    5 3
    4 2 4 5 1
    输出样例#1:
    6

    说明

    对于20%的数据,有N≤10;

    对于40%的数据,有N≤1000;

    对于100%的数据,有N≤100000,M≤N, A[i]之和不超过10^9。

    思路:

      这道题可以用二分答案+前缀和来做,但是我搞了好久依旧是80分,不知道哪里错了...

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int M = 1e5 + 8;
    int n,m,maxx,minn;
    int sum[M],a[M];
    int ans;
    
    bool calc(int now)
    {
        int mm=maxx;
        int cnt=0,last=0;
        int i=1;
        while(cnt<m)
        {
            while(sum[i]-sum[last]<=now)
                i++;
            i--;
            mm=mm-(sum[i]-sum[last]);
            last=i;
            cnt++;
            if(mm<=0) return 1;
        }
        return 0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            maxx+=a[i];
            if(minn<a[i])
             minn=a[i];
            sum[i]=sum[i-1]+a[i];
        }
        sum[n+1]=0x7fffffff;///因为之后要用到sum[n+1]来进行操作 
        int l=minn,r=maxx;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(calc(mid)) r=(ans=mid)-1;
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
    My View Code
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int M = 1e5 + 8;
    int n,m,maxx,minn;
    int sum[M],a[M];
    int ans;
    
    bool calc(int now)
    {
        int tmp=0,total=0;
        for(int i=1;i<=n;i++)
        {
            if(total+a[i]<=now)
                total+=a[i];
            else///若超出当前枚举到的答案最大值 
            {
                tmp++;///新的一段
                total=a[i]; 
            }
        }
        if(tmp<m) return 1;
        return 0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            maxx+=a[i];
            if(minn<a[i])
             minn=a[i];
        }
        int l=minn,r=maxx;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(calc(mid)) r=(ans=mid)-1;
            else l=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
    AC View Code

    End.

    如果运气好也是错,那我倒愿意错上加错!

    ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

  • 相关阅读:
    javaweb基础(6)_servlet配置参数
    javaweb基础(5)_servlet原理
    读书笔记:java特种兵(上)
    基础算法(四):海量数据的处理方法
    基础算法(三)动态规划和贪心算法
    基础算法(二):堆排序,快速排序
    基本算法(一):插入排序,归并排序
    JVM基础和调优(六)
    JVM基础和调优(五)
    JVM基础和调优(四)
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/6826545.html
Copyright © 2011-2022 走看看