二分用于在单调序列上以logn的时间确定某个值,三分则用在凸函数上,即先增后减序列,可以找它的极值。我们需要mid=(l+r)/2和midmid=(mid+r)/2这两个分界点,前者大则令r=midmid,否则令l=mid。 例题:cf939E 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include<bits/stdc++.h> using namespace std; const int maxn=5e5+1; double a[maxn]; double sum[maxn]; int p,q; #define cal(k) (a[p]-(a[p]+sum[k])/(k+1)) int main(){ cin>>q; while(q--){ int tp; cin>>tp; if(tp==1){ double x; cin>>x; a[++p]=x; sum[p]=sum[p-1]+a[p]; }else{ int l=1,r=p; //三分 while(l<r-1){ int mid=(l+r)/2; int midmid=(mid+r)/2; if(cal(mid)<cal(midmid)){ l=mid; }else{ r=midmid; } } double ans=max(cal(l),cal(r)); printf("%.6f\n",ans); } } return 0; }