二分算法:平均值(洛谷 UVA1451)
生活随笔
收集整理的這篇文章主要介紹了
二分算法:平均值(洛谷 UVA1451)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
解析
這道題尋找平均值的max,答案明顯具有單調(diào)性,所以采用二分算法
從0到1不斷取中點(diǎn)mid作為平均值的可能點(diǎn),看是否存在不短于l的數(shù)列均值>=mid不難得到以下代碼:
現(xiàn)在的問(wèn)題就是要解決這個(gè)check函數(shù)的寫(xiě)法了
因?yàn)镹范圍到1e5,暴力的On方肯定是會(huì)超的
我們想到可以先把數(shù)組都減mid,這樣就轉(zhuǎn)化為是否存在不短于L的數(shù)列加和大于等于0的問(wèn)題
我們用s[i]表示1到i的加和
那么a到b的和可以轉(zhuǎn)化為s[b] - s[a-1](其中b-a+1 >=l)
要使s[b] - s[a-1]最大,就要使s[a-1]取的是s[0]到s[b-l+1]的最大值
而隨著b從l循環(huán)到n,每次s[a-1]只加入了一個(gè)可能取的元素,故只需與該新值取min,不必遍歷
代碼如下:
這樣check函數(shù)的時(shí)間復(fù)雜度就為O(n)
AC快樂(lè)~~~~~~
代碼
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int M = 2e9; int n,l,t; int zuo,you; int f[100500]; bool check(double x){double s[100500]={ };s[1]=f[1] - x;for(int i=2;i<=n;i++){s[i] = s[i-1] + f[i] -x;//求減完x的前綴和 }double mn=M;for(int i=l;i<=n;i++){mn=min(mn,s[i-l]);if(s[i]-mn>=0) return true;//只要存在就返回true }return false; } int main(){scanf("%d",&t);for(int k=1;k<=t;k++){scanf("%d%d",&n,&l);for(int i=1;i<=n;i++){scanf("%1d",&f[i]);}double st=0,ed=1;for(int i=1;i<=10;i++){double mid=(st+ed)/2;if(check(mid)) st=mid;else ed=mid;}double x=st;double s[100500]={ };s[1]=f[1] - x;for(int i=2;i<=n;i++){s[i] = s[i-1] + f[i] -x;}int a,flag=0;double mn=M;for(int i=l;i<=n;i++){if(mn>s[i-l]){mn=s[i-l];a=i-l;}if(s[i]-mn>=0){if(flag==0){zuo=a+1;you=i;flag=1;}else if(you-zuo>i-a){zuo=a+1;you=i;}}}printf("%d %d\n",zuo,you);}return 0; }祝大家rp++!
總結(jié)
以上是生活随笔為你收集整理的二分算法:平均值(洛谷 UVA1451)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: “此WINDOWS副本不是正版”彻底解决
- 下一篇: 字符串:凯撒密码(洛谷P1914)