zoukankan      html  css  js  c++  java
  • 【题解】P4343 [SHOI2015]自动刷题机

    原题地址

    简化题面:一个数,初始为0。(l)次操作,每次给这个数加上 (xi)(xi)可能为负),如果其小于0则变成0,如果大于等于(n)则变成0并给(ans)加1。已知最后的(ans)等于(k),求(n)可能的最小值和最大值。如果没有满足条件的(n),输出-1。

    对于一眼看到此题,很难想到二分来做,考虑怎么想到的二分

    举个栗子

    假如两个(n),一个8一个9,假如第一次增加9,对于(n=8)来说剩余1,对于(n=9)来说剩余0,在剩余的增加次数中无论怎样8总会领先于9(ans)到达(k),因此可见对于不同的(n),对于到达(k)(ans)的贡献是单调的,可以进行二分

    想到了二分,此题就很好做了,我们二分(n),对于答案的判断直接进行题面模拟的,逐步压缩空间直到符合答案

    有关二分

    对于二分有两种格式,下面简单提一下

    对于求符合答案区间的最小值,也就是左边箭头所指的值,我们的二分过程如下

    while(l < r){
    	int mid = (l + r) >> 1;
        if(a[mid] >= x) r = mid;else l = mid + 1;
    }
    return a[l];
    

    对于最大值,也就是右边箭头所指的值,我们的二分过程如下

    while(l < r){
    	int mid = (l + r + 1) >> 1;
        if(a[mid] <= x) l = mid; else r = mid - 1;
    }
    return a[l];
    

    个人认为二分类型的题很练人的细节程度,建议仔细品一品过程并且自己模拟一下~

    (Code)

    #include<bits/stdc++.h>
        
    #define LL long long
        
    #define int long long
    
    #define _ 0
        
    using namespace std;
        
    /*Grievous Lady*/
        
    template <typename T> void read(T & t){
        t = 0;int f = 1;char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-')f =- 1;ch = getchar();}
        do{t = t * 10 + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');t *= f;
    }
    
    #define INF 0x3f3f3f3f3f3f3f3fLL
    
    const int kato = 1e5 + 10;
    
    int a , k;
    
    int x[kato];
    
    inline int judge(int mid){
        int sum = 0 , tot = 0;
        for(int i = 1;i <= a;i ++){
            sum += x[i];
            if(sum < 0) sum = 0;
            if(sum >= mid) tot ++ , sum = 0;
        }
        return tot;
    }
    
    inline int Ame_(){
        read(a);read(k);
        for(int i = 1;i <= a;i ++){
            read(x[i]);
        }
        int la = 1 , ra = INF , ansa = INF;
        while(la < ra){
            int mida = (la + ra) >> 1;
            if(judge(mida) <= k){
                ra = mida;
            }
            else la = mida + 1;
            // cout << ansa << '
    ';
        }
        if(judge(la) == k) ansa = la;
        if(ansa != INF) printf("%lld " , ansa);
        else printf("-1 ");
        int lb = 1 , rb = INF , ansb = INF;
        while(lb < rb){
            int midb = (lb + rb + 1) >> 1;
            if(judge(midb) >= k){ 
                lb = midb;
                // if(judge(lb) == k) ansb = lb;
            }
            else rb = midb - 1;
        }
        if(judge(lb) == k) ansb = lb;
        if(ansb != INF) printf("%lld
    " , ansb);
        return ~~(0^_^0);
    }
        
    int Ame__ = Ame_();
        
    signed main(){;}
    
  • 相关阅读:
    js基础
    linux 权限计算
    postman 测试http post的json请求
    Crontab 让linux定时执行shell脚本
    Java:扫描包含图片的文件夹,将符合分辨率格式的复制出来
    php引用其他目录的php文件
    电脑屏幕动图制作之-----GifCam
    通过Excel表创建sql脚本
    通过Navicat将Excel表中的数据导入到数据库
    需求设计之初造火箭?
  • 原文地址:https://www.cnblogs.com/Ame-sora/p/13429662.html
Copyright © 2011-2022 走看看