1. 程式人生 > >【noip模擬賽6】收入計劃 最大值的最小值 二分答案

【noip模擬賽6】收入計劃 最大值的最小值 二分答案

con card 兩個 space 最小值 一次 就會 pre iii

描述

高考結束後,同學們大都找到了一份臨時工作,渴望掙得一些零用錢。從今天起,Matrix67將連續工作N天(1<=N<=100 000)。每一天末他可以領取當天及前面若幹天裏沒有領取的工資,但他總共只有M(1<=M<=N)次領取工資的機會。Matrix67已經知道了在接下來的這N天裏每一天他可以賺多少錢。為了避免自己濫用零花錢,他希望知道如何安排領取工資的時間才能使得領到工資最多的那一次工資數額最小。註意Matrix67必須恰好領工資M次,且需要將所有的工資全部領走(即最後一天末需要領一次工資)。

輸入

第一行輸入兩個用空格隔開的正整數N和M

以下N行每行一個不超過10000正整數,依次表示每一天的薪水。

輸出

輸出領取到的工資的最大值最小是多少。

輸入樣例 1

7 5
100
400
300
100
500
101
400

輸出樣例 1

500

提示

【樣例說明】

采取下面的方案可以使每次領到的工資不會多於500。這個答案不能再少了。

100 400 300 100 500 101 400 每一天的薪水

<------1 <-------2 <---3 <---4 <---5 領取工資的時間

500 400 500 101 400 領取到的工資

老是想著用dp

之前做過一次最大值的最小值二分答案 以後一定要引起警覺

二分答案的時候出現了很多小錯誤

有以下兩種寫法要註意:

技術分享圖片
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define
LL long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define N 100005 int a[N]; int main() { int n,m; RII(n,m); long sum=0; int maxx=0; rep(i,1,n) { RI(a[i]); sum+=a[i]; maxx=max(maxx,a[i]); } long long L=maxx; long long R=sum; int ans; while(L<R) { long long sum=0; long long mid=(L+R)>>1; int cnt=0; rep(i,1,n) { if(sum+a[i]>mid) { cnt++;sum=a[i]; } else sum+=a[i]; } if(sum)cnt++; if(cnt>m)L=mid+1; else R=mid; //如果寫成這樣就會錯 因為mid是趨向左的 如果L和M差1 那麽將進入死循環 if(cnt>=m)L=mid; else R=mid-1; } cout<<R; }
View Code 技術分享圖片
#include<bits/stdc++.h>
using namespace std;
//input
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 100005
int a[N];

int main()
{
    int n,m;
    RII(n,m);
    long sum=0;
    int maxx=0;
    rep(i,1,n)
    {
        RI(a[i]);
        sum+=a[i];
        maxx=max(maxx,a[i]);
    }

    long long L=maxx;
    long long R=sum;
   int ans;
    while(L<=R)
    {
        int cnt=0;
        long long sum=0;
        long long mid=(L+R)>>1;
       
        rep(i,1,n)
        {
            if(sum+a[i]>mid)
            {
                cnt++;sum=a[i];
            }
            else
                sum+=a[i];
        }
        if(sum)cnt++;
        
        if(cnt>m)L=mid+1;
        else  ans=mid,R=mid-1;

    }
    cout<<ans;

}
View Code

【noip模擬賽6】收入計劃 最大值的最小值 二分答案