P4343 [SHOI2015]自动刷题机-二分的两种情况

[SHOI2015]自动刷题机

题目背景

曾经发明了信号增幅仪的发明家 SHTSC 又公开了他的新发明:自动刷题机——一种可以自动 AC 题目的神秘装置。

题目描述

自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序。每秒,自动刷题机的代码生成模块会有两种可能的结果:

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

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

输入格式

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

接下来 l l l 行,每行一个整数 x i x_i xi,依次表示每条日志。若 x i ≥ 0 x_i \geq 0 xi0,则表示写了 x i x_i xi 行代码,若 x i < 0 x_i \lt 0 xi<0,则表示删除了 − x i -x_i xi 行代码。

输出格式

输出一行两个整数,分别表示 n n n 可能的最小值和最大值。
如果这样的 n n n 不存在,请输出一行一个整数 − 1 -1 1

样例 #1

样例输入 #1

4 2
2
5
-3
9

样例输出 #1

3 7
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<x<<" ";
#define Pu puts("");
#define sf(x) scanf("%d",&x);
typedef long long ll;
const int N=1e5+10,mod=100003;
int n, m;
ll an1, an2;
int a[N];
int fun(ll x){
    int res = 0;
    ll t = 0;//这里可能会爆int
    for(int i = 1; i <= n; i++){
        t += a[i];
        if(t < 0){//如果y大于之前的代码长度,则相当于全部删除
            t = 0;
        }else if(t >= x){//注意这里,如果此时代码长度大于x,则说明已经完成一个题目
            res++;
            t = 0;
        }
    }
    return res;
}
int main(){
    cin >> n >> m;
    for(int i = 1; i <= n; i ++){
        sf(a[i])
    }
    ll l = 1, r = 1e18, mid;
    int t;
    while(l < r){//找第一个大于等于的值
        mid = (l + r) >> 1;
        t = fun(mid);
        if(t == m){
            r = mid;//注意这里的区别
        }else if(t > m){//此时解决的题目数量多于m,则应该增大每个题目需要代码量
            l = mid + 1;
        }else{
            r = mid;
        }
    }
    an1 = l;

    l = 1, r = 1e18;
    while(l < r){//找第一个大于的值
        mid = (l + r) >> 1;
        t = fun(mid);
        if(t == m){
            l = mid + 1;//注意这里的区别
        }else if(t > m){//此时解决的题目数量多于m,则应该增大每个题目需要代码量
            l = mid + 1;
        }else{
            r = mid;
        }
    }
    an2 = l - 1;
    if(fun(an1) != m) printf("-1\n");
    else{
        de(an1)de(an2)
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值