先說一下二分,二分其實就是跳着枚舉.一點點縮小區間,到最後就聚成一個點.中間能夠不用枚舉那麼多數.只\(check\)一下中間值\(mid\)是否能夠,而後再轉換到左半區間或者右半區間,這個看題目要求了.而後就這樣跳着走.\(so\) \(fast\);ios
\(check\)函數其實就是檢驗一下\(mid\)是否符合題目要求.大概平時都是\(bool\)型的.git
下面看一個例子題.
洛谷P1281 書的複製
題目描述
如今要把\(m\)本有順序的書分給\(k\)給人複製(抄寫),每個人的抄寫速度都同樣,一本書不容許給兩個(或以上)的人抄寫,分給每個人的書,必須是連續的,好比不能把第1、第3、第四本書給同一我的抄寫。函數
如今請你設計一種方案,使得複製時間最短。複製時間爲抄寫頁數最多的人用去的時間。
輸入格式
第一行兩個整數\(m,k;(k≤m≤500)\)spa
第二行\(m\)個整數,第\(i\)個整數表示第\(i\)本書的頁數。
輸出格式
共\(k\)行,每行兩個整數,第\(i\)行表示第\(i\)我的抄寫的書的起始編號和終止編號。\(k\)行的起始編號應該從小到大排列,若是有多解,則儘量讓前面的人少抄寫。
輸入輸出樣例
輸入設計
9 3 1 2 3 4 5 6 7 8 9
輸出code
1 5 6 7 8 9
思路
全部每一個人的頁數最大值在\(1到\sum_{i=1}^na_i\) 之間,因此0左右左端點,\(\sum_{i=1}^na_i\)做爲右端點,就能夠開始二分了,\(check\)函數,若是遇到了比\(mid\)頁數大的書,那麼每一個人最多\(mid\)頁也無法整完這一本由於一本書只能給一我的,而後就左端點\(=mid+1\)繼續找更大的,不然就右端點\(=mid-1\)找更小的,blog
上\(check\)函數ip
bool check(int x) { int tot=0,js=0; for(int i=m;i>=1;i--) { if(i==1) js++; if(a[i]>x) return false; if(tot+a[i]<=x)//累加 tot+=a[i]; else//若是這我的不能再繼續抄下一本了就換一個新人, tot=a[i],js++; } return js<=k; }
這道題,對我的認爲二分的考察不大,二分卻是不難寫,感受難寫的是輸出的時候有點費腦.get
總代碼string
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<iomanip> #include<cstdlib> #include<queue> #include<map> #include<set> #include<stack> #include<vector> #define ll long long using namespace std; inline int read() { int s=0,w=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} while(isdigit(ch)) s=s*10+ch-'0',ch=getchar(); return s*w; } int m,k,a[550],l,r,x,jb,okoj,jk,b[550][5],ojk,js; bool check(int x) { int tot=0,js=0; for(int i=m;i>=1;i--) { if(i==1) js++; if(a[i]>x) return false; if(tot+a[i]<=x) tot+=a[i]; else tot=a[i],js++; } return js<=k; } int main() { m=read(),k=read(); if(m==0&&k==0) return 0; for(int i=1;i<=m;i++) a[i]=read(),js+=a[i]; l=0,r=js; while(l<=r) { int mid=l+r>>1; if(check(mid)) okoj=mid,r=mid-1; else l=mid+1; } x=m; for(int i=m;i>=1;i--) { jb+=a[i]; if(jb>l) { b[++ojk][1]=i+1,b[ojk][2]=x; jb=a[i],x=i; } } if(js<=l) { return printf("1 %d",m),0; } printf("1 %d\n",max(b[ojk][1]-1,1)); for(int i=ojk;i>=1;i--) printf("%d %d\n",b[i][1],b[i][2]); return 0; }
附帥照