zoukankan      html  css  js  c++  java
  • 「BZOJ4590」「SHOI2015」 自动刷题机 解题报告

    自动刷题机

    Description

    曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置。自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模块会有两种可能的结果:

    A.写了x行代码。
    B.心情不好,删掉了之前写的y行代码。(如果y大于当前代码长度则相当于全部删除。)

    对于每个OJ所有题目,存在某个固定的长度n>0。一旦自动刷题机在某秒结束时积累了大于等于n行的代码,它就会自动提交并AC此题,然后新建一个文件开始写下一题。SHTSC在某个OJ上跑了一天的自动刷题机,得到了很多条关于写代码的日志信息。他突然发现自己没有记录这个OJ的n究竟是多少。所幸他通过自己在OJ上的Rank知道了机一共切了k道题。希望你计算n可能的最小值和最大值。

    Input

    第一行两个整数l,k,表示刷题机的日志一共有l行,一共了切了k题。

    第二行l个整数,(x_1…x_l。)(x_i ge 0)表示写了(x_i)行代码。(x_i<0)表示删除了这道题的(-x_i)行代码。

    (1 le l,k le 100000,left| x_i ight| le10^9)

    Output

    输出两个数a,b。分别代表n可能的最小值和最大值。如果不存在这样的n则输出-1。

    Sample Input

    4 2
    2
    5
    -3
    9
    

    Sample Output

    3 7
    

    样例1:如果n=2那么刷题机就会切掉3题。但如果n>7刷题机最多只能切1题。考虑n=4发生了什么。
    第一秒:刷题机写了2行。
    第二秒:刷题机又写了5行,共有7行,提交,自信AC。
    第三秒:刷题机删掉了3行,共有0行。
    第四秒:刷题机写了9行,共有9行,提交,自信AC。
    一共AC了两题。


    思路

    这是一道二分题。 没错这就是一道二分题。

    它的单调性很明显。n越大,切的题就越少。 所以,话不多说——直接切入正题。

    这里要求最小值(ans1)与最大值(ans2),所以要写2个二分,一个判断条件是(check(mid) > k) 另一个是 (ge)

    ans1要加1,因为(>k)求出的是 满足 (check(mid) > k) 的 最大值。如果有答案的话,(ans1 + 1)必定是满足(check(mid) = k)最小值。

    话不多说,直接上代码((〃'▽'〃)——)

    代码

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define LL long long
    
    int l, k;
    LL a[100005];
    LL le(1), ri, ans1, ans2, mid;
    
    LL check( LL x ){//模拟求切题数
        LL cur(0), s(0);
        for ( int i = 1; i <= l; ++i ){
            cur = max( cur + a[i], 0ll );
            if ( cur >= x ){
                s++; cur = 0;
            }
        }
        return s;
    }
    
    int main(){
        scanf( "%d%d", &l, &k );
        for ( int i = 1; i <= l; ++i ) scanf( "%lld", &a[i] );
        le = 1; ri = 1000000000000000;//边界是个坑,走远一点就不会掉进去了嘛(`・ω・´)反正时间复杂度不会超过O(100)
        while( le <= ri ){
            mid = ( le + ri ) >> 1;
            if ( check( mid ) > k ){
                le = mid + 1;
                ans1 = mid;
            }
            else ri = mid - 1;
        }
        ans1++;
        le = 1; ri = 1000000000000000;
        while( le <= ri ){
            mid = ( le + ri ) >> 1;
            if ( check( mid ) >= k ){
                le = mid + 1;
                ans2 = mid;
            }
            else ri = mid - 1;
        }
        if ( check( ans1 ) != k ) printf( "-1
    " );
        else printf( "%lld %lld
    ", ans1, ans2 );
        return 0;
    }
    
  • 相关阅读:
    swift NSComparator
    Java mac 上编写Java代码
    四舍五入、上取整、下取整
    数组排序
    删除xcode 里的多余证书
    启动画面 设置
    CGFloat Float 互转
    navigationController pop的几种方法
    iOS 获取键盘相关信息
    eclipse代码格式化
  • 原文地址:https://www.cnblogs.com/louhancheng/p/10060803.html
Copyright © 2011-2022 走看看