← INDEX DOCUMENT

【luoguP4343】自动刷题机

题目

题目背景

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

题目描述

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

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

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

输入格式

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

接下来 (l) 行,每行一个整数 (x_i)​,依次表示每条日志。若 (x_i)≥0,则表示写了 (x_i)行代码,若 (x_i)<0,则表示删除了 -(x_i)行代码。

输出格式

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

数据范围

对于 20% 的数据,保证 (l≤10)

对于 40% 的数据,保证 (l≤100)

对于 60% 的数据,保证 (l≤2×10^3)

对于 100% 的数据,保证 $1≤l≤(10^5)

链接:

https://www.luogu.com.cn/problem/P4343

思路

初看想法

第一眼看到这个题目的数据范围,显然不是用暴力求解,先试试20%数据

20%数据

20%数据显然可以通过枚举n嘛,把n枚举出来再看看能否切掉k道题目就可以了。等等……枚举n?

100%数据

既然要枚举n,那完全可以用二分来枚举。这不就是一题二分答案嘛,只不过要求一个最大值一个最小值,两次二分就能解决了。

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
ll a[100000+10];
ll pd(ll x){
ll sum=0,t=0;
for(int i=1;i<=n;i++){
sum+=a[i];
if(sum<0) sum=0;
if(sum>=x) t++,sum=0;
}
return t;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
ll left=1,right=1e14;
ll minans=-1,maxans=-1;
while(left<=right){
ll mid=(left+right)/2;
ll d=pd(mid);
if(d==k) minans=mid,right=mid-1;
else if(d<k) right=mid-1;
else left=mid+1;
}
left=1,right=1e14;
while(left<=right){
ll mid=(left+right)/2;
ll d=pd(mid);
if(d==k) maxans=mid,left=mid+1;
else if(d<k) right=mid-1;
else left=mid+1;
}
if(minans==-1&&maxans==-1) cout<<-1;
else
cout<<minans<<' '<<maxans;
}