【二分答案】自动刷题机(洛谷P4343)

题目描述

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

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

1. 心情很好,写了 xi 行代码;

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

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

输入

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

接下来 L 行,每行一个整数 xi,依次表示每条日志。若 xi ≥ 0,则表示写了 xi 行代码,若 xi < 0,则表示删除了 yi = −xi 行代码。

输出

输出一行两个整数,分别表示 n 可能的最小值和最大值。

注意:如果这样的 n 不存在,请输出一行,这一行只有一个整数 −1。

数据范围限制

Solution:

通过及其复杂的证明(指快两面pdf的证明),蓝鹅考场上随便手推假设了几个情况就可以想到题目符合单调性,即n越大切得题越少

然后就容易想到用二分答案,众所周知,若存在多个答案,通过修改二分策略可以实现查询最大和最小的答案

 值得一提的是,就是如何判断输出-1,二分答案不管如何也会能给你找出个答案,所以说我们可以对最后的答案进行check,如何没有正好等于K就输出-1

Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define max(a,b) a>b?a:b
 4 int L,K,X[100050];
 5 long long Maxx,Minn,Ans;
 6 bool Check(long long T,int Mode){
 7     long long Deal=0; 
 8     int Res=0;
 9     for(int i=1;i<=L;i++){
10         Deal+=X[i];
11         Deal=(Deal<0)?0:Deal;
12         if(Deal>=T){
13             Deal=0;
14             Res++;
15         }
16     }
17     if(Mode==1){
18         if(Res<=K) return true;
19         else return false;
20     }
21     if(Mode==2){
22         if(Res>=K) return true;
23         else return false;
24     }
25     if(Mode==3){
26         if(Res==K) return true;
27         else return false;
28     }
29     return (1+1==2);
30 }
31 int main()
32 {
33     freopen("automaton.in","r",stdin);
34     freopen("automaton.out","w",stdout);
35     scanf("%d%d",&L,&K);
36     for(int i=1;i<=L;i++){
37         scanf("%d",&X[i]); 
38     }
39     //Search Minn
40     long long L=1,R=1e14+7;
41     while(L<=R){
42         long long Mid=(L+R)/2;
43         if(Check(Mid,1)){
44             Ans=Mid;
45             R=Mid-1;
46         } 
47         else L=Mid+1;
48     }
49     Minn=Ans;
50 //=============================================
51     //Search Maxx
52     L=1,R=1e14+7;
53     Ans=0;
54     while(L<=R){
55         long long Mid=(L+R)/2;
56         if(Check(Mid,2)){
57             Ans=Mid;
58             L=Mid+1;
59         } 
60         else R=Mid-1;
61     }
62     Maxx=Ans;
63     if(!Check(Maxx,3)) cout<<-1;
64     else cout<<Minn<<" "<<Maxx; 
65     return 0;
66 }
原文地址:https://www.cnblogs.com/Takarada-Rikka/p/13540178.html