1. 程式人生 > >【BZOJ4590】自動刷題機

【BZOJ4590】自動刷題機

lin long long 自動 etc getchar 沒有 如果 urn type

【思路分析】

比賽的時候想到了用二分+貪心,二分的部分與貪心的部分也寫對了,但是由於數據範圍未看沒有開long long,且二分左端點賦值過小導致WA掉

正解:二分+貪心

二分代碼的長度,貪心判斷能否達到,算法上沒什麽好說的,主要是細節處理上

關於細節處理:

  1. 開long long
  2. 右端點數據可以開的盡量大一點
  3. 輸出-1的點要特別小心

代碼:

#include<cstdio>
#include<cmath>
#include<cctype>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
using namespace std;
inline long long read()
{
    char chr=getchar();
    long long f=1,ans=0;
    while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
    while(isdigit(chr))  {ans=(ans<<1)+(ans<<3)+chr-'0';chr=getchar();}
    return ans*f;
}
long long n,m,a[100005],l=1,r,mid,ans1=-1,ans2=-1;
inline long long check(long long x){//貪心判斷解是否可行 
    long long s=0,num=0;
    for(int i=1;i<=n;i++){
        s+=a[i];
        if(s<0) s=0;
        if(s>=x) s=0,num++;
    }
    return num;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    r=1e18;//開得盡量大一點
    while(l<=r){
        mid=l+r>>1;
        if(check(mid)<=m)   ans1=mid,r=mid-1;
                else    l=mid+1;
    }//取最小值
    l=1,r=1e18;
    while(l<=r){
        mid=l+r>>1;
        if(check(mid)<m)    ans2=mid,r=mid-1;
                else    l=mid+1;
    }//取最大值
    ans2--;
    if(ans1>ans2||ans1==-1||ans2==-1) {//如果ans1沒有更新過 或者 ans2沒有更新過 或者 
    //小的答案大於大的答案
        printf("-1");
        return 0;
    }
    printf("%lld %lld",ans1,ans2);
    return 0;
}

【BZOJ4590】自動刷題機