• 【二分答案】自动刷题机(洛谷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 }
  • 相关阅读:
    浅谈最长上升子序列(LIS)
    浅谈树链剖分
    数字计数
    windy数
    骑士(树形dp)
    旅游规划
    皇宫看守
    k8s安装报错
    linux文件夹存储潜规则
    搭建覆盖率测试环境
  • 原文地址:https://www.cnblogs.com/Takarada-Rikka/p/13540178.html
Copyright © 2020-2023  润新知