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个整数,x1…xl。xi>=0表示写了xi行代码。xi<0表示删除了这道题的-xi行代码。
1<=l,k<=100000,|xi|<=10^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$满足单调性,两次二分答案即可。注意答案的上下界。

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define inf (1000000000000000LL)
14 #define N (200010)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19 
20 using namespace std;
21 
22 ll a[N],n,k,ans1,ans2;
23 
24 il ll gi(){
25     RG ll x=0,q=1; RG char ch=getchar();
26     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
27     if (ch=='-') q=-1,ch=getchar();
28     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
29     return q*x;
30 }
31 
32 il ll check(RG ll key){
33     RG ll sum=0,tot=0;
34     for (RG ll i=1;i<=n;++i){
35     sum=max(sum+a[i],0LL);
36     if (sum>=key) ++tot,sum=0;
37     }
38     return tot;
39 }
40 
41 il void findmin(){
42     RG ll l=1,r=inf,mid;
43     while (l<=r){
44     mid=(l+r)>>1;
45     if (check(mid)<=k) ans1=mid,r=mid-1; else l=mid+1;
46     }
47     return;
48 }
49 
50 il void findmax(){
51     RG ll l=1,r=inf,mid;
52     while (l<=r){
53     mid=(l+r)>>1;
54     if (check(mid)>=k) ans2=mid,l=mid+1; else r=mid-1;
55     }
56     return;
57 }
58 
59 il void work(){
60     n=gi(),k=gi(); for (RG ll i=1;i<=n;++i) a[i]=gi(); findmin(),findmax();
61     if (check(ans1)!=k || check(ans2)!=k) puts("-1");
62     else printf("%lld %lld
",ans1,ans2); return;
63 }
64 
65 int main(){
66     File("auto");
67     work();
68     return 0;
69 }
原文地址:https://www.cnblogs.com/wfj2048/p/7110992.html